- int svm_fd;
- svm_region_t *rp;
- pthread_mutexattr_t attr;
- pthread_condattr_t cattr;
- int deadman=0;
- u8 junk = 0;
- void *oldheap;
- int overhead_space;
- int rv;
- uword data_base;
- int nbits, words, bit;
- int pid_holding_region_lock;
- u8 *shm_name;
- int dead_region_recovery = 0;
- int time_left;
- struct stat stat;
- struct timespec ts, tsrem;
-
- if (CLIB_DEBUG > 1)
- clib_warning ("[%d] map region %s", getpid(), a->name);
-
- ASSERT((a->size & ~(MMAP_PAGESIZE-1)) == a->size);
- ASSERT(a->name);
-
- shm_name = shm_name_from_svm_map_region_args (a);
-
- svm_fd = shm_open((char *) shm_name, O_RDWR | O_CREAT | O_EXCL, 0777);
-
- if (svm_fd >= 0) {
- if (fchmod (svm_fd, 0770) < 0)
- clib_unix_warning ("segment chmod");
- /* This turns out to fail harmlessly if the client starts first */
- if (fchown (svm_fd, a->uid, a->gid) < 0)
- clib_unix_warning ("segment chown [ok if client starts first]");
-
- vec_free(shm_name);
-
- if (lseek(svm_fd, a->size, SEEK_SET) == (off_t) -1) {
- clib_warning ("seek region size");
- close (svm_fd);
- return (0);
- }
- if (write(svm_fd, &junk, 1) != 1) {
- clib_warning ("set region size");
- close (svm_fd);
- return (0);
- }
-
- rp = mmap((void *)a->baseva, a->size,
- PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, svm_fd, 0);
-
- if (rp == (svm_region_t *) MAP_FAILED) {
- clib_unix_warning ("mmap create");
- close (svm_fd);
- return (0);
- }
- close(svm_fd);
- memset(rp, 0, sizeof(*rp));
-
- if (pthread_mutexattr_init(&attr))
- clib_unix_warning("mutexattr_init");
-
- if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED))
- clib_unix_warning("mutexattr_setpshared");
-
- if (pthread_mutex_init(&rp->mutex, &attr))
- clib_unix_warning("mutex_init");
-
- if (pthread_mutexattr_destroy(&attr))
- clib_unix_warning("mutexattr_destroy");
-
- if (pthread_condattr_init(&cattr))
- clib_unix_warning("condattr_init");
-
- if (pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED))
- clib_unix_warning("condattr_setpshared");
-
- if (pthread_cond_init(&rp->condvar, &cattr))
- clib_unix_warning("cond_init");
-
- if(pthread_condattr_destroy(&cattr))
- clib_unix_warning("condattr_destroy");
-
- region_lock (rp, 1);
-
- rp->virtual_base = a->baseva;
- rp->virtual_size = a->size;
-
- rp->region_heap =
- mheap_alloc_with_flags ((void *)(a->baseva+MMAP_PAGESIZE),
- SVM_PVT_MHEAP_SIZE,
- MHEAP_FLAG_DISABLE_VM);
- oldheap = svm_push_pvt_heap(rp);
-
- rp->region_name = (char *)format (0, "%s%c", a->name, 0);
- vec_add1(rp->client_pids, getpid());
-
- nbits = rp->virtual_size / MMAP_PAGESIZE;
-
- ASSERT (nbits > 0);
- rp->bitmap_size = nbits;
- words = (nbits + BITS(uword)-1) / BITS(uword);
- vec_validate (rp->bitmap, words-1);
-
- overhead_space = MMAP_PAGESIZE /* header */ +
- SVM_PVT_MHEAP_SIZE;
-
- bit = 0;
- data_base = (uword)rp->virtual_base;
-
- if (a->flags & SVM_FLAGS_NODATA)
- rp->flags |= SVM_FLAGS_NEED_DATA_INIT;
-
- do {
- clib_bitmap_set_no_check (rp->bitmap, bit, 1);
- bit++;
- overhead_space -= MMAP_PAGESIZE;
- data_base += MMAP_PAGESIZE;
- } while (overhead_space > 0);
-
- rp->data_base = (void *)data_base;
-
- /*
- * Note: although the POSIX spec guarantees that only one
- * process enters this block, we have to play games
- * to hold off clients until e.g. the mutex is ready
- */
- rp->version = SVM_VERSION;
-
- /* setup the data portion of the region */
-
- rv = svm_data_region_create (a, rp);
- if (rv) {
- clib_warning ("data_region_create: %d", rv);
- }
-
- region_unlock(rp);
-
- svm_pop_heap(oldheap);
-
- return ((void *) rp);
- } else {
- svm_fd = shm_open((char *)shm_name, O_RDWR, 0777);
-
- vec_free(shm_name);
-
- if (svm_fd < 0) {
- perror("svm_region_map(mmap open)");
- return (0);
- }
-
- time_left = 20;
- while (1) {
- if (0 != fstat(svm_fd, &stat)) {
- clib_warning("fstat failed: %d", errno);
- close (svm_fd);
- return (0);
- }
- if (stat.st_size > 0) {
- break;
- }
- if (0 == time_left) {
- clib_warning("waiting for resize of shm file timed out");
- close (svm_fd);
- return (0);
- }
- ts.tv_sec = 0;
- ts.tv_nsec = 100000000;
- while (nanosleep(&ts, &tsrem) < 0)
- ts = tsrem;
- time_left--;
- }
-
- rp = mmap(0, MMAP_PAGESIZE,
- PROT_READ | PROT_WRITE, MAP_SHARED, svm_fd, 0);
-
- if (rp == (svm_region_t *) MAP_FAILED) {
- close(svm_fd);
- clib_warning("mmap");
- return (0);
- }
- /*
- * We lost the footrace to create this region; make sure
- * the winner has crossed the finish line.
- */
- while (rp->version == 0 && deadman++ < 5) {
- sleep(1);
- }
-
- /*
- * <bleep>-ed?
- */
- if (rp->version == 0) {
- clib_warning("rp->version %d not %d", rp->version,
- SVM_VERSION);
- close(svm_fd);
- munmap(rp, a->size);
- return (0);
- }
- /* Remap now that the region has been placed */
- a->baseva = rp->virtual_base;
- a->size = rp->virtual_size;
- munmap(rp, MMAP_PAGESIZE);
-
- rp = (void *) mmap ((void *)a->baseva, a->size,
- PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_FIXED, svm_fd, 0);
- if ((uword)rp == (uword)MAP_FAILED) {
- clib_unix_warning ("mmap");
- close (svm_fd);
- return (0);
- }
-
- if ((uword) rp != rp->virtual_base) {
- clib_warning("mmap botch");
- }
-
- /*
- * Try to fix the region mutex if it is held by
- * a dead process
- */
- pid_holding_region_lock = rp->mutex_owner_pid;
- if (pid_holding_region_lock &&
- kill (pid_holding_region_lock, 0) < 0) {
- clib_warning (
- "region %s mutex held by dead pid %d, tag %d, force unlock",
- rp->region_name, pid_holding_region_lock, rp->mutex_owner_tag);
- /* owner pid is nonexistent */
- rp->mutex.__data.__owner = 0;
- rp->mutex.__data.__lock = 0;
- dead_region_recovery = 1;
- }
-
- if (dead_region_recovery)
- clib_warning ("recovery: attempt to re-lock region");
-
- region_lock(rp, 2);
- oldheap = svm_push_pvt_heap (rp);
- vec_add1(rp->client_pids, getpid());
-
- if (dead_region_recovery)
- clib_warning ("recovery: attempt svm_data_region_map");
-
- rv = svm_data_region_map (a, rp);
- if (rv) {
- clib_warning ("data_region_map: %d", rv);
- }
-
- if (dead_region_recovery)
- clib_warning ("unlock and continue");
-
- region_unlock(rp);
-
- svm_pop_heap(oldheap);
-
- return ((void *) rp);
+ int svm_fd;
+ svm_region_t *rp;
+ pthread_mutexattr_t attr;
+ pthread_condattr_t cattr;
+ int deadman = 0;
+ u8 junk = 0;
+ void *oldheap;
+ int overhead_space;
+ int rv;
+ uword data_base;
+ int nbits, words, bit;
+ int pid_holding_region_lock;
+ u8 *shm_name;
+ int dead_region_recovery = 0;
+ int time_left;
+ struct stat stat;
+ struct timespec ts, tsrem;
+
+ if (CLIB_DEBUG > 1)
+ clib_warning ("[%d] map region %s", getpid (), a->name);
+
+ ASSERT ((a->size & ~(MMAP_PAGESIZE - 1)) == a->size);
+ ASSERT (a->name);
+
+ shm_name = shm_name_from_svm_map_region_args (a);
+
+ svm_fd = shm_open ((char *) shm_name, O_RDWR | O_CREAT | O_EXCL, 0777);
+
+ if (svm_fd >= 0)
+ {
+ if (fchmod (svm_fd, 0770) < 0)
+ clib_unix_warning ("segment chmod");
+ /* This turns out to fail harmlessly if the client starts first */
+ if (fchown (svm_fd, a->uid, a->gid) < 0)
+ clib_unix_warning ("segment chown [ok if client starts first]");
+
+ vec_free (shm_name);
+
+ if (lseek (svm_fd, a->size, SEEK_SET) == (off_t) - 1)
+ {
+ clib_warning ("seek region size");
+ close (svm_fd);
+ return (0);
+ }
+ if (write (svm_fd, &junk, 1) != 1)
+ {
+ clib_warning ("set region size");
+ close (svm_fd);
+ return (0);
+ }
+
+ rp = mmap ((void *) a->baseva, a->size,
+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, svm_fd, 0);
+
+ if (rp == (svm_region_t *) MAP_FAILED)
+ {
+ clib_unix_warning ("mmap create");
+ close (svm_fd);
+ return (0);
+ }
+ close (svm_fd);
+ memset (rp, 0, sizeof (*rp));
+
+ if (pthread_mutexattr_init (&attr))
+ clib_unix_warning ("mutexattr_init");
+
+ if (pthread_mutexattr_setpshared (&attr, PTHREAD_PROCESS_SHARED))
+ clib_unix_warning ("mutexattr_setpshared");
+
+ if (pthread_mutex_init (&rp->mutex, &attr))
+ clib_unix_warning ("mutex_init");
+
+ if (pthread_mutexattr_destroy (&attr))
+ clib_unix_warning ("mutexattr_destroy");
+
+ if (pthread_condattr_init (&cattr))
+ clib_unix_warning ("condattr_init");
+
+ if (pthread_condattr_setpshared (&cattr, PTHREAD_PROCESS_SHARED))
+ clib_unix_warning ("condattr_setpshared");
+
+ if (pthread_cond_init (&rp->condvar, &cattr))
+ clib_unix_warning ("cond_init");
+
+ if (pthread_condattr_destroy (&cattr))
+ clib_unix_warning ("condattr_destroy");
+
+ region_lock (rp, 1);
+
+ rp->virtual_base = a->baseva;
+ rp->virtual_size = a->size;
+
+ rp->region_heap =
+ mheap_alloc_with_flags ((void *) (a->baseva + MMAP_PAGESIZE),
+ (a->pvt_heap_size != 0) ?
+ a->pvt_heap_size : SVM_PVT_MHEAP_SIZE,
+ MHEAP_FLAG_DISABLE_VM);
+ oldheap = svm_push_pvt_heap (rp);
+
+ rp->region_name = (char *) format (0, "%s%c", a->name, 0);
+ vec_add1 (rp->client_pids, getpid ());
+
+ nbits = rp->virtual_size / MMAP_PAGESIZE;
+
+ ASSERT (nbits > 0);
+ rp->bitmap_size = nbits;
+ words = (nbits + BITS (uword) - 1) / BITS (uword);
+ vec_validate (rp->bitmap, words - 1);
+
+ overhead_space = MMAP_PAGESIZE /* header */ +
+ ((a->pvt_heap_size != 0) ? a->pvt_heap_size : SVM_PVT_MHEAP_SIZE);
+
+ bit = 0;
+ data_base = (uword) rp->virtual_base;
+
+ if (a->flags & SVM_FLAGS_NODATA)
+ rp->flags |= SVM_FLAGS_NEED_DATA_INIT;