X-Git-Url: http://nsz.repo.hu/git/?p=musl;a=blobdiff_plain;f=src%2Fthread%2Fsem_open.c;h=d8d68392add362538a2c5c619db56c9792faba0c;hp=55d5ef6b7808bae8e070e1d979d0b67083407375;hb=97c5b5a87c3d9df54278e1073d6177f77536bd32;hpb=6fc5fdbdc70dd17ea8e681a361fb4dae541ee953 diff --git a/src/thread/sem_open.c b/src/thread/sem_open.c index 55d5ef6b..d8d68392 100644 --- a/src/thread/sem_open.c +++ b/src/thread/sem_open.c @@ -9,32 +9,32 @@ #include #include #include +#include +#include -static void *find_map(int fd) +static struct { + ino_t ino; + sem_t *sem; + int refcnt; +} *semtab; + +static int semcnt; +static pthread_spinlock_t lock; +static pthread_once_t once; + +static void init() { - char c; - struct stat st; - FILE *f; - void *addr; - unsigned long long off, ino; - char buf[100]; + semtab = calloc(sizeof *semtab, SEM_NSEMS_MAX); +} - if (fstat(fd, &st) < 0) return 0; - if (!(f = fopen("/proc/self/maps", "rb"))) return 0; - - while (fgets(buf, sizeof buf, f)) { - sscanf(buf, "%lx-%*lx %*s %llx %*x:%*x %llu /dev/shm%c", - (long *)&addr, &off, &ino, &c); - while (!strchr(buf, '\n') && fgets(buf, sizeof buf, f)); - if (c!='/') continue; - c = 0; - if (!off && st.st_ino == ino) { - fclose(f); - return addr; - } - } - fclose(f); - return 0; +static sem_t *find_map(ino_t ino) +{ + int i; + for (i=0; i= 0 || errno != ENOENT) { if (flags & O_CREAT) { close(dir); close(tfd); unlink(tmp); } - if (fd < 0) return SEM_FAILED; - if ((map = find_map(fd))) + if (fd >= 0 && fstat(fd, &st) < 0) { + close(fd); + fd = -1; + } + if (fd < 0) { + pthread_spin_unlock(&lock); + return SEM_FAILED; + } + if ((map = find_map(st.st_ino))) { + pthread_spin_unlock(&lock); + close(fd); + if (map == (sem_t *)-1) + return SEM_FAILED; return map; + } break; } } + if (!(flags & O_CREAT)) { + pthread_spin_unlock(&lock); + return SEM_FAILED; + } if (!linkat(AT_FDCWD, tmp, dir, name, 0)) { fd = tfd; close(dir); @@ -109,8 +135,40 @@ sem_t *sem_open(const char *name, int flags, ...) return SEM_FAILED; } } + if (fstat(fd, &st) < 0) { + pthread_spin_unlock(&lock); + close(fd); + return SEM_FAILED; + } + if (semcnt == SEM_NSEMS_MAX) { + pthread_spin_unlock(&lock); + close(fd); + errno = EMFILE; + return SEM_FAILED; + } + for (i=0; i