--- e2fsprogs-1.39/lib/uuid/Makefile.in +++ e2fsprogs-1.39/lib/uuid/Makefile.in @@ -19,6 +19,8 @@ OBJS= clear.o \ compare.o \ copy.o \ + pv.o \ + shm.o \ gen_uuid.o \ isnull.o \ pack.o \ @@ -30,6 +32,8 @@ SRCS= $(srcdir)/clear.c \ $(srcdir)/compare.c \ $(srcdir)/copy.c \ + $(srcdir)/pv.c \ + $(srcdir)/shm.c \ $(srcdir)/gen_uuid.c \ $(srcdir)/isnull.c \ $(srcdir)/pack.c \ @@ -82,7 +86,7 @@ uuid_time: $(srcdir)/uuid_time.c $(DEPLIBUUID) @echo " LD $@" - @$(CC) $(ALL_CFLAGS) -DDEBUG -o uuid_time $(srcdir)/uuid_time.c \ + @$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -DDEBUG -o uuid_time $(srcdir)/uuid_time.c \ $(LIBUUID) uuid.3: $(DEP_SUBSTITUTE) $(srcdir)/uuid.3.in --- e2fsprogs-1.39/lib/uuid/gen_uuid.c +++ e2fsprogs-1.39/lib/uuid/gen_uuid.c @@ -71,6 +71,10 @@ #endif #include "uuidP.h" +#include "pv.h" +#include "shm.h" +#include +#include #ifdef HAVE_SRANDOM #define srand(x) srandom(x) @@ -224,42 +228,55 @@ /* Assume that the gettimeofday() has microsecond granularity */ #define MAX_ADJUSTMENT 10 +static pthread_once_t m_uuid_init_guard = PTHREAD_ONCE_INIT; +static pthread_mutex_t m_uuid_mutex = PTHREAD_MUTEX_INITIALIZER; +static int m_uuid_sem_id = -1; + +void m_uuid_init_once() +{ + m_uuid_sem_id = uuid_sem_init((int)'u'); +} + static int get_clock(uint32_t *clock_high, uint32_t *clock_low, uint16_t *ret_clock_seq) { - static int adjustment = 0; - static struct timeval last = {0, 0}; - static uint16_t clock_seq; - struct timeval tv; - unsigned long long clock_reg; - + unsigned long long clock_reg; + struct timeval tv; + static uint16_t clock_seq; + static int adjustment = 0; + + int shm_id = shm_init((int)'s', sizeof(struct timeval)); + struct timeval *clock_time = (struct timeval*)shm_addr(shm_id); + try_again: gettimeofday(&tv, 0); - if ((last.tv_sec == 0) && (last.tv_usec == 0)) { + if ((clock_time->tv_sec == 0) && (clock_time->tv_usec == 0)) { get_random_bytes(&clock_seq, sizeof(clock_seq)); clock_seq &= 0x3FFF; - last = tv; - last.tv_sec--; + *clock_time = tv; + clock_time->tv_sec--; } - if ((tv.tv_sec < last.tv_sec) || - ((tv.tv_sec == last.tv_sec) && - (tv.tv_usec < last.tv_usec))) { + if ((tv.tv_sec < clock_time->tv_sec) || + ((tv.tv_sec == clock_time->tv_sec) && + (tv.tv_usec < clock_time->tv_usec))) { clock_seq = (clock_seq+1) & 0x3FFF; adjustment = 0; - last = tv; - } else if ((tv.tv_sec == last.tv_sec) && - (tv.tv_usec == last.tv_usec)) { + *clock_time = tv; + } else if ((tv.tv_sec == clock_time->tv_sec) && + (tv.tv_usec == clock_time->tv_usec)) { if (adjustment >= MAX_ADJUSTMENT) goto try_again; adjustment++; } else { adjustment = 0; - last = tv; + *clock_time = tv; } - + + clock_seq = (clock_seq+1) & 0x3FFF; + clock_reg = tv.tv_usec*10 + adjustment; - clock_reg += ((unsigned long long) tv.tv_sec)*10000000; - clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000; - + clock_reg += ((unsigned long)tv.tv_sec)*10000000; + clock_reg += (((unsigned long long)0x01B21DD2) << 23) + 0x13814000; + *clock_high = clock_reg >> 32; *clock_low = clock_reg; *ret_clock_seq = clock_seq; @@ -268,10 +285,16 @@ void uuid_generate_time(uuid_t out) { + pthread_mutex_lock(&m_uuid_mutex); + + pthread_once(&m_uuid_init_guard, m_uuid_init_once); + + if(m_uuid_sem_id != -1) uuid_sem_P(m_uuid_sem_id); + static unsigned char node_id[6]; static int has_init = 0; struct uuid uu; - uint32_t clock_mid; + uint32_t clock_mid; if (!has_init) { if (get_node_id(node_id) <= 0) { @@ -291,6 +314,10 @@ uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; memcpy(uu.node, node_id, 6); uuid_pack(&uu, out); + + if(m_uuid_sem_id != -1) uuid_sem_V(m_uuid_sem_id); + + pthread_mutex_unlock(&m_uuid_mutex); } void uuid_generate_random(uuid_t out) --- e2fsprogs-1.39/lib/uuid/pv.c +++ e2fsprogs-1.39/lib/uuid/pv.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include + +#if defined(PV_REPORT_VERBOSE) +#include + +#define report(msg) perror(msg) +#else +#define report(msg) +#endif +#include + +#include "pv.h" + +int uuid_sem_init(int project_id) +{ + key_t sem_key; + int sem_id; + + sem_key = ftok("/", project_id); + if(sem_key == (key_t)-1) + { + report("Can't generate semaphore key"); + return -1; + } + + sem_id = semget(sem_key, 0, 0); + if(sem_id == -1) + { + sem_id = semget(sem_key, 1, IPC_CREAT | IPC_EXCL | + S_IRUSR | S_IWUSR | S_IRGRP | + S_IWGRP | S_IROTH | S_IWOTH); + if(sem_id != -1) + { + union semun { + int val; + struct semid_ds *buf; + unsigned short *array; + struct seminfo *__buf; + } arg; + arg.val = 1; + + if(semctl(sem_id, 0, SETVAL, arg) == -1) + { + report("Can't initialize semaphore"); + + /* try to remove -- we've created it */ + semctl(sem_id, 0, IPC_RMID, (int)0); + sem_id = -1; + } + } + else + if(errno == EEXIST) + { + if( (sem_id = semget(sem_key, 0, 0)) == -1) + { + report("Can't acquire / create semahore"); + } + } + else + { + report("Can't neither acquire nor create semahore"); + } + } + return sem_id; +} + +static inline int sem_pv(int id, int op) +{ + struct sembuf sb; + sb.sem_num = 0; + sb.sem_op = op; + sb.sem_flg = /*SEM_UNDO*/0; + return semop(id, &sb, 1); +} + +int uuid_sem_P(int id) +{ + return sem_pv(id, -1); +} + +int uuid_sem_V(int id) +{ + return sem_pv(id, 1); +} + --- e2fsprogs-1.39/lib/uuid/pv.h +++ e2fsprogs-1.39/lib/uuid/pv.h @@ -0,0 +1,9 @@ +#ifndef PV_H_INCLUDE_GUARD +#define PV_H_INCLUDE_GUARD + +int uuid_sem_init(int project_id); +int uuid_sem_P(int id); +int uuid_sem_V(int id); + +#endif // PV_H_INCLUDE_GUARD + --- e2fsprogs-1.39/lib/uuid/shm.c +++ e2fsprogs-1.39/lib/uuid/shm.c @@ -0,0 +1,43 @@ +#include +#include +#include + +#if defined(SHM_REPORT_VERBOSE) +#include + +#define report(msg) perror(msg) +#else +#define report(msg) +#endif +#include + +#include "shm.h" + +int shm_init(int project_id, size_t size) { + key_t key; + int id; + + key = ftok("/", project_id); + if (key == (key_t)-1) { + report("Can't generate shared memory key"); + return -1; + } + + id = shmget(key, 0, 0); + if (id == -1) { + id = shmget(key, size, 0666 | IPC_CREAT); + if (id == -1 && errno == EEXIST) { + if ((id = shmget(key, 0, 0)) == -1) { + report("Can't acquire/create shared memory"); + } + } + else if (id == -1) { + report("Can neither acquire nor create shared memory"); + } + } + return id; +} + +void *shm_addr(int id) { + return shmat(id, NULL, 0); +} --- e2fsprogs-1.39/lib/uuid/shm.h +++ e2fsprogs-1.39/lib/uuid/shm.h @@ -0,0 +1,9 @@ +#ifndef SHM_H_INCLUDE_GUARD +#define SHM_H_INCLUDE_GUARD + +#include + +int shm_init(int project_id, size_t size); +void *shm_addr(int id); + +#endif // SHM_H_INCLUDE_GUARD