Exemplo n.º 1
0
Arquivo: init.c Projeto: zswek/bitch
void mm_init(void) {
    
    gdt_init();
    
    mmap_init();
    
}
Exemplo n.º 2
0
void __init proc_caches_init(void)
{
	sighand_cachep = kmem_cache_create("sighand_cache",
			sizeof(struct sighand_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_DESTROY_BY_RCU|
			SLAB_NOTRACK, sighand_ctor);
	signal_cachep = kmem_cache_create("signal_cache",
			sizeof(struct signal_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL);
	files_cachep = kmem_cache_create("files_cache",
			sizeof(struct files_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL);
	fs_cachep = kmem_cache_create("fs_cache",
			sizeof(struct fs_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL);
	/*
	 * FIXME! The "sizeof(struct mm_struct)" currently includes the
	 * whole struct cpumask for the OFFSTACK case. We could change
	 * this to *only* allocate as much of it as required by the
	 * maximum number of CPU's we can ever have.  The cpumask_allocation
	 * is at the end of the structure, exactly for that reason.
	 */
	mm_cachep = kmem_cache_create("mm_struct",
			sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL);
	vm_area_cachep = KMEM_CACHE(vm_area_struct, SLAB_PANIC);
	mmap_init();
	nsproxy_cache_init();
}
Exemplo n.º 3
0
static void
init_commands(void)
{
	attr_init();
	bmap_init();
	fadvise_init();
	file_init();
	freeze_init();
	fsync_init();
	getrusage_init();
	help_init();
	imap_init();
	inject_init();
	madvise_init();
	mincore_init();
	mmap_init();
	open_init();
	parent_init();
	pread_init();
	prealloc_init();
	fiemap_init();
	pwrite_init();
	quit_init();
	resblks_init();
	sendfile_init();
	shutdown_init();
	truncate_init();
}
Exemplo n.º 4
0
void __start(struct bios_service_table *pbios_services)
{
    bios_services = pbios_services;
    __asm("xchg %bx, %bx");
    bios_console_init(&bios_console);
    stdout->handle.pointer = &bios_console.dev;

    /* Initialize the memory map, find all the tables. */
    mmap_init();
    tables_init();
    vbe_init();

    /*gd_memory_map_entry mmap[100]; size_t nentries = 100, key = 0;
    mmap_get(&mmap, nentries, &nentries, &key);
    for (size_t i = 0; i < nentries; i++) {
        printf("Entry %d: %llx -> %llx, %d\n", i, mmap[i].physical_start,
               mmap[i].physical_start + mmap[i].size,
               mmap[i].type);
    }*/

    //extern gd_rsdt_pointer_table rsdt_pointer;
    //extern gd_pc_pointer_table pc_pointer;

    //if (rsdt_pointer.header.length) {
    //    printf("RSDT: %x\nXSDT: %llx\n", rsdt_pointer.rsdt_address, rsdt_pointer.xsdt_address);
    //}

    //if (pc_pointer.header.length) {
    //    printf("MPS: %c%c%c%c\nSMBIOS: %x\n", pc_pointer.mpfp.signature[0],
    //                                          pc_pointer.mpfp.signature[1],
    //                                          pc_pointer.mpfp.signature[2],
    //                                          pc_pointer.mpfp.signature[3], pc_pointer.smbios_entry_point_address);
    //}
    for(;;);
}
Exemplo n.º 5
0
//This function initialize the camera device and V4L2 interface
void video_record_init(){
	//open camera
	camera_fd = open(camera_name, O_RDWR );
	if(camera_fd == -1){
		printf("error opening camera %s\n", camera_name);
		return;
	}

	set_camera_output_format();
	buffers = NULL;
	decompressed_frame_camera = NULL;
	mmap_init();
}
Exemplo n.º 6
0
void __init proc_caches_init(void)
{
	sighand_cachep = kmem_cache_create("sighand_cache",
			sizeof(struct sighand_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_DESTROY_BY_RCU,
			sighand_ctor);
	signal_cachep = kmem_cache_create("signal_cache",
			sizeof(struct signal_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
	files_cachep = kmem_cache_create("files_cache",
			sizeof(struct files_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
	fs_cachep = kmem_cache_create("fs_cache",
			sizeof(struct fs_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
	mm_cachep = kmem_cache_create("mm_struct",
			sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
	mmap_init();
}
Exemplo n.º 7
0
void __init proc_caches_init(void)
{
	sighand_cachep = kmem_cache_create("sighand_cache",
			sizeof(struct sighand_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_DESTROY_BY_RCU|
			SLAB_NOTRACK, sighand_ctor);
	signal_cachep = kmem_cache_create("signal_cache",
			sizeof(struct signal_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL);
	files_cachep = kmem_cache_create("files_cache",
			sizeof(struct files_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL);
	fs_cachep = kmem_cache_create("fs_cache",
			sizeof(struct fs_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL);
	mm_cachep = kmem_cache_create("mm_struct",
			sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL);
	vm_area_cachep = KMEM_CACHE(vm_area_struct, SLAB_PANIC);
	mmap_init();
	nsproxy_cache_init();
}
Exemplo n.º 8
0
/***********************************************************************
 *           wine_init
 *
 * Main Wine initialisation.
 */
void wine_init( int argc, char *argv[], char *error, int error_size )
{
    struct dll_path_context context;
    char *path;
    void *ntdll = NULL;
    void (*init_func)(void);

    /* force a few limits that are set too low on some platforms */
#ifdef RLIMIT_NOFILE
    set_max_limit( RLIMIT_NOFILE );
#endif
#ifdef RLIMIT_AS
    set_max_limit( RLIMIT_AS );
#endif

    wine_init_argv0_path( argv[0] );
    build_dll_path();
    __wine_main_argc = argc;
    __wine_main_argv = argv;
    __wine_main_environ = environ;
    mmap_init();

    for (path = first_dll_path( "ntdll.dll", 0, &context ); path; path = next_dll_path( &context ))
    {
        if ((ntdll = wine_dlopen( path, RTLD_NOW, error, error_size )))
        {
            /* if we didn't use the default dll dir, remove it from the search path */
            if (default_dlldir[0] && context.index < nb_dll_paths + 2) nb_dll_paths--;
            break;
        }
    }
    free_dll_path( &context );

    if (!ntdll) return;
    if (!(init_func = wine_dlsym( ntdll, "__wine_process_init", error, error_size ))) return;
    init_func();
}
Exemplo n.º 9
0
Arquivo: region.c Projeto: RAttab/ilka
struct ilka_region * ilka_open(const char *file, struct ilka_options *options)
{
    journal_recover(file);

    struct ilka_region *r = calloc(1, sizeof(struct ilka_region));
    if (!r) {
        ilka_fail("out-of-memory for ilka_region struct: %lu",
                sizeof(struct ilka_region));
        return NULL;
    }

    slock_init(&r->lock);

    r->file = file;
    r->options = *options;

    if ((r->fd = file_open(file, &r->options)) == -1) goto fail_open;
    if ((r->len = file_grow(r->fd, ILKA_PAGE_SIZE)) == -1UL) goto fail_grow;
    if (!mmap_init(&r->mmap, r->fd, r->len, &r->options)) goto fail_mmap;
    if (!persist_init(&r->persist, r, r->file)) goto fail_persist;

    const struct meta * meta = meta_read(r);
    if (meta->magic != ilka_magic) {
        if (!r->options.create) {
            ilka_fail("invalid magic for file '%s'", file);
            goto fail_magic;
        }

        struct meta * m = meta_write(r);
        m->magic = ilka_magic;
        m->version = ilka_version;
        m->alloc = sizeof(struct meta);
    }

    if (meta->version != ilka_version) {
        ilka_fail("invalid version for file '%s': %lu != %lu",
                file, meta->version, ilka_version);
        goto fail_version;
    }

    if (!alloc_init(&r->alloc, r, &r->options, meta->alloc)) goto fail_alloc;
    if (!epoch_init(&r->epoch, r, &r->options)) goto fail_epoch;
    if (ILKA_MCHECK) mcheck_init(&r->mcheck);

    r->header_len = alloc_end(&r->alloc);

    return r;

  fail_epoch:
  fail_alloc:
  fail_version:
  fail_magic:
    persist_close(&r->persist);

  fail_persist:
    mmap_close(&r->mmap);

  fail_mmap:
  fail_grow:
    file_close(r->fd);

  fail_open:
    free(r);
    return NULL;
}
Exemplo n.º 10
0
Arquivo: mmap.c Projeto: aunali1/exopc
void *mmap (void *addr, size_t len, int prot, int flags, int fd,
	    off_t offset)
{

  u_int pageoff;
  caddr_t ret;
  off_t pos = offset;
  size_t size = len;
  struct Mmap *m;
  struct stat sb;
  struct file *filp;
  struct mmap_ustruct *mus;

  OSCALLENTER(OSCALL_mmap);
  if (!mmap_inited) mmap_init();

  /* if given a bad fd then return */
  if (fd != -1 && fstat (fd, &sb) < 0) {
    errno = EINVAL;
    OSCALLEXIT(OSCALL_mmap);
    return (caddr_t )-1;
  }

  if ((flags & MAP_COPY) && (flags & MAP_ANON)) flags &= ~MAP_COPY;

  /* OpenBSD 2.1 code */
  /*
   * Align the file position to a page boundary,
   * and save its page offset component.
   */
  pageoff = (pos & PGMASK);
  pos -= pageoff;

  /* Adjust size for rounding (on both ends). */
  size += pageoff;	/* low end... */
  size = PGROUNDUP(size); /* hi end */

  /* Do not allow mappings that cause address wrap... */
  if ((ssize_t)size < 0) {
    errno = EINVAL;
    OSCALLEXIT(OSCALL_mmap);
    return (caddr_t)-1;
  }

  /*
   * Check for illegal addresses.  Watch out for address wrap...
   */
  if (flags & MAP_FIXED) {
    /*
     * The specified address must have the same remainder
     * as the file offset taken modulo NBPG, so it
     * should be aligned after adjustment by pageoff.
     */
    addr -= pageoff;
    if ((u_int)addr & PGMASK) {
      errno = EINVAL;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }
    /* Address range must be all in user VM space. */
    if (UTOP > 0 && (u_int)addr + size > UTOP) {
      errno = EINVAL;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }
    if ((u_int)addr > (u_int)addr + size) {
      errno = EINVAL;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }
  }

  if ((flags & MAP_ANON) == 0) {
    if (fd < 0 || fd > NR_OPEN || __current->fd[fd] == NULL) {
      errno = EBADF;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }

    /*
     * XXX hack to handle use of /dev/zero to map anon
     * memory (ala SunOS).
     */
    if (S_ISCHR(__current->fd[fd]->f_mode) &&
	mmap_iszerodev(__current->fd[fd]->f_dev)) {
      flags |= MAP_ANON;
      goto is_anon;
    }

    /*
     * Only files and cdevs are mappable, and cdevs does not
     * provide private mappings of any kind.
     */
    if (!S_ISREG(__current->fd[fd]->f_mode) &&
	(!S_ISCHR(__current->fd[fd]->f_mode) ||
	 (flags & (MAP_PRIVATE|MAP_COPY)))) {
      errno = EINVAL;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }

    /*
     * Ensure that file and memory protections are
     * compatible.  Note that we only worry about
     * writability if mapping is shared; in this case,
     * current and max prot are dictated by the open file.
     * XXX use the vnode instead?  Problem is: what
     * credentials do we use for determination?
     * What if proc does a setuid?
     */
    if (((__current->fd[fd]->f_flags & O_ACCMODE) == O_WRONLY) &&
	(prot & PROT_READ)) {
      errno = EACCES;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }

    /*
     * If we are sharing potential changes (either via MAP_SHARED
     * or via the implicit sharing of character device mappings),
     * and we are trying to get write permission although we
     * opened it without asking for it, bail out.
     */
    if (((flags & MAP_SHARED) != 0 || S_ISCHR(__current->fd[fd]->f_mode)) &&
	((__current->fd[fd]->f_flags & O_ACCMODE) == O_RDONLY) &&
	(prot & PROT_WRITE) != 0) {
      errno = EACCES;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }
  } else {
    /*
     * (flags & MAP_ANON) == TRUE
     * Mapping blank space is trivial.
     */
    if (fd != -1) {
      errno = EINVAL;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }
  is_anon:
    pos = 0;
  }

  if (size == 0) {
    OSCALLEXIT(OSCALL_mmap);
    return addr; 
  }

  if (fd >= 0)
    filp = __current->fd[fd];
  else
    filp = NULL;

  if ((flags & MAP_FIXED) == 0) {
    addr = __malloc(size);
    if (addr == NULL) {
      __free(addr);
      errno = ENOMEM;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }
  }

  mus = exos_pinned_malloc(sizeof(*mus));
  if (mus == NULL) {
    if ((flags & MAP_FIXED) == 0) __free(addr);
    errno = ENOMEM;
    OSCALLEXIT(OSCALL_mmap);
    return (caddr_t)-1;
  }

  m = &(mus->m);
  m->mmap_addr = addr;
  m->mmap_len = size;
  m->mmap_prot = prot;
  m->mmap_flags = flags;
  m->mmap_offset = pos;
  m->mmap_filp = filp;
  m->mmap_dev = ((fd != -1) ? sb.st_dev : 0);
  LIST_INSERT_HEAD (&mmap_list, m, mmap_link);

  mus->mru.handler = mmap_fault_handler;
  mus->oldmru = mregion_get_ustruct(addr); /* XXX - check return value */

  if (__vm_free_region((u_int)addr, size, 0) < 0 ||
      mregion_alloc(addr, size, (struct mregion_ustruct*)mus) != 0) {
    if ((flags & MAP_FIXED) == 0) __free(addr);
    exos_pinned_free(mus);
    errno = ENOMEM;
    OSCALLEXIT(OSCALL_mmap);
    return (caddr_t)-1;
  }

  if (filp) {
    lock_filp(filp);
    filp_refcount_inc(filp);
    unlock_filp(filp);
  }

  if (flags & MAP_COPY)
    ret = __mmap(addr, size, prot, flags, fd, pos, 0, __envid);
  else
    ret = addr + pageoff;

  OSCALLEXIT(OSCALL_mmap);
  return ret;
}
Exemplo n.º 11
0
void
init()
{
	struct ext_mem_format *ptr_exts; // structure-pointer to structure
	struct ext_mem_format temp_struc; // temporary structure
	struct inode ino_kern;
	struct ext_mem_format ext_mem_strucs[50]; // 386 usable RAM list format

	usec_t ino_sec;
	ubyte_t num_servs; // number of servers to read to memory
	uint_t tot_mem, counter, counter1; // counters
	byte *ptr_mem=(byte *)ext_mem_strucs; // byte-pointer to structure

	/* 
	 * Get absolute sector for first ivector.
	 * It is stored in a global variable.
	 */
	sosfs_ivec_first();

	/* read kernel's and server's inode sector */
	ino_sec = sosfs_iget("/boot/kernel");
	/* if error */
	if (ino_sec == -1) {
		low_putstr("Inode not found\n"); 
		while (1);
	}
	/* read kernel's inode */
	sosfs_read_raw(ino_sec, &ino_kern);

	/* zero out the vector */
	for (tot_mem=0; tot_mem<512; tot_mem++)
		buffer[tot_mem]=0;

	/* 
	 * Copy arguments from real-mode to protected-mode.
	 * The monitor program wishes to pass the arguments to the kernel.
	 * This is done by a little hack that uses an interrupt instruction
	 * passing a buffer to copy from real-mode to protected-mode using
	 * BIOS.
	 */
	kargs_init();

	/* 
	 * Get total amount of RAM.
	 * The most reliable way to know the system's memory-mapping
	 * is by using the BIOS; we use int $0x15 function 0xe820.
	 */
	low_tot_ram(ext_mem_strucs);

	/* point to memory-map vector */
	ptr_exts=ext_mem_strucs;
	/* 
	 * Traverse the structures until magic number found.
	 * Our interrupt handler set a magic number after the last
	 * entry returned by the BIOS handler.
	 */
	kprintf("\n");
	kprintf("BIOS-provided physical-memory mappings\n");
	kprintf("======================================================\n");
	while (ptr_exts->acpi_ext != 0x12345) {
		/* if we must ignore the entry, so we do */
		if (ptr_exts->reg_len == 0)
			continue;
		/* print type of memory to terminal */
		switch (ptr_exts->reg_type) {
			case 1:
				kprintf("Usable RAM at ");
				if (ptr_exts->base_addr[0] != 0) {
					zero_mem(ptr_exts);
					put_list(ptr_exts);
				}
				break;
			case 2:
				kprintf("Reserved/unusable RAM at ");
				break;
			case 3:
			case 4:
			case 5:
				kprintf("ACPI RAM at ");
				break;
		}
		/*
		 * Create a temporary structure and copy the entire structure
		 * to it.
		 * Print the address range.
		 */
		temp_struc = *ptr_exts; // copy structure
		temp_struc.reg_len[0] += temp_struc.base_addr[0];
		kprintf("%x-", &temp_struc);
		kprintf("%x", temp_struc.reg_len);
		kprintf("\n");
		for (tot_mem=0; tot_mem<512; tot_mem++)
			buffer[tot_mem]=0;
		ptr_exts++; // advance one structure
	}
	kprintf("======================================================\n");

	/* 
	 * Set up initial memory mappings.
	 * Load user-level servers to predefined physical memory and
	 * identically map them. Map the monitor program and the kernel
	 * also to identical physical addresses. Also map those programs'
	 * heaps.
	 */
	load_init();
	heap_init();
	/* list returned by BIOS might be unsorted */
	sort_free_list();
	/* machine-dependent format to machine-independent format */
	dep_2_indep_list(ptr_list);
	mmap_init();
	enable_paging();
	SOS_init();
}
Exemplo n.º 12
0
Arquivo: v4l2.c Projeto: AWilco/xbmc
static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
{
    struct video_data *s = s1->priv_data;
    AVStream *st;
    int res;
    uint32_t desired_format, capabilities;
    enum CodecID codec_id;

    st = av_new_stream(s1, 0);
    if (!st) {
        return AVERROR(ENOMEM);
    }
    av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */

    s->width  = ap->width;
    s->height = ap->height;

    capabilities = 0;
    s->fd = device_open(s1, &capabilities);
    if (s->fd < 0) {
        return AVERROR(EIO);
    }
    av_log(s1, AV_LOG_VERBOSE, "[%d]Capabilities: %x\n", s->fd, capabilities);

    if (!s->width && !s->height) {
        struct v4l2_format fmt;

        av_log(s1, AV_LOG_VERBOSE, "Querying the device for the current frame size\n");
        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) {
            av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", strerror(errno));
            return AVERROR(errno);
        }
        s->width  = fmt.fmt.pix.width;
        s->height = fmt.fmt.pix.height;
        av_log(s1, AV_LOG_VERBOSE, "Setting frame size to %dx%d\n", s->width, s->height);
    }

    desired_format = device_try_init(s1, ap, &s->width, &s->height, &codec_id);
    if (desired_format == 0) {
        av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for "
               "codec_id %d, pix_fmt %d.\n", s1->video_codec_id, ap->pix_fmt);
        close(s->fd);

        return AVERROR(EIO);
    }
    if (av_image_check_size(s->width, s->height, 0, s1) < 0)
        return AVERROR(EINVAL);
    s->frame_format = desired_format;

    if (v4l2_set_parameters(s1, ap) < 0)
        return AVERROR(EIO);

    st->codec->pix_fmt = fmt_v4l2ff(desired_format, codec_id);
    s->frame_size = avpicture_get_size(st->codec->pix_fmt, s->width, s->height);
    if (capabilities & V4L2_CAP_STREAMING) {
        s->io_method = io_mmap;
        res = mmap_init(s1);
        if (res == 0) {
            res = mmap_start(s1);
        }
    } else {
        s->io_method = io_read;
        res = read_init(s1);
    }
    if (res < 0) {
        close(s->fd);

        return AVERROR(EIO);
    }
    s->top_field_first = first_field(s->fd);

    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
    st->codec->codec_id = codec_id;
    st->codec->width = s->width;
    st->codec->height = s->height;
    st->codec->time_base.den = ap->time_base.den;
    st->codec->time_base.num = ap->time_base.num;
    st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8;

    return 0;
}
Exemplo n.º 13
0
/**
 * Initializes the shared structures.
 */
static void shared_init()
{
  APIRET arc;
  int rc;

  arc = DosExitList(EXLST_ADD, ProcessExit);
  ASSERT_MSG(arc == NO_ERROR, "%ld", arc);

#if defined(TRACE_ENABLED) && !defined(TRACE_USE_LIBC_LOG)
  /*
   * Allocate a larger buffer to fit lengthy TRACE messages and disable
   * auto-flush on EOL (to avoid breaking lines by stdout operations
   * from other threads/processes).
   */
  setvbuf(stdout, NULL, _IOFBF, 0x10000);
#endif

  while (1)
  {
    /* First, try to open the mutex */
    arc = DosOpenMutexSem(MUTEX_LIBCX, &gMutex);
    TRACE("DosOpenMutexSem = %lu\n", arc);

    if (arc == NO_ERROR)
    {
      /*
       * Init is (being) done by another process, request the mutex to
       * guarantee shared memory is already alloated, then get access to
       * it and open shared heap located in that memory.
       */
      arc = DosRequestMutexSem(gMutex, SEM_INDEFINITE_WAIT);
      ASSERT_MSG(arc == NO_ERROR, "%ld", arc);

      if (arc == NO_ERROR)
      {
        arc = DosGetNamedSharedMem((PPVOID)&gpData, SHAREDMEM_LIBCX, PAG_READ | PAG_WRITE);
        TRACE("DosGetNamedSharedMem = %lu\n", arc);
        if (arc)
        {
          /*
           * This failure means that another process was too fast to do what
           * it wanted and initiated global uninitialization before we got the
           * mutex so shared memory was already freed by this time. Retry.
           */
          DosReleaseMutexSem(gMutex);
          DosCloseMutexSem(gMutex);
          continue;
        }

        /*
         * It's an ordinary LIBCx process. Increase coutners.
         */

        TRACE("gpData->heap = %p\n", gpData->heap);
        ASSERT(gpData->heap);

        rc = _uopen(gpData->heap);
        ASSERT_MSG(rc == 0, "%d (%d)", rc, errno);

        ASSERT(gpData->refcnt);
        gpData->refcnt++;
        TRACE("gpData->refcnt = %d\n", gpData->refcnt);
      }

      break;
    }

    if (arc == ERROR_SEM_NOT_FOUND)
    {
      /* We are the first process, create the mutex */
      arc = DosCreateMutexSem(MUTEX_LIBCX, &gMutex, 0, TRUE);
      TRACE("DosCreateMutexSem = %ld\n", arc);

      if (arc == ERROR_DUPLICATE_NAME)
      {
        /* Another process is faster, attempt to open the mutex again */
        continue;
      }
    }

    ASSERT_MSG(arc == NO_ERROR, "%ld", arc);

    /*
     * It's a process that successfully created the main mutex, i.e. the first
     * LIBCx process. Proceed with the initial setup by allocating shared
     * memory and heap.
     */

    /* Allocate shared memory */
    arc = DosAllocSharedMem((PPVOID)&gpData, SHAREDMEM_LIBCX, HEAP_SIZE,
                            PAG_READ | PAG_WRITE | OBJ_ANY);
    TRACE("DosAllocSharedMem(OBJ_ANY) = %ld\n", arc);

    if (arc && arc != ERROR_ALREADY_EXISTS)
    {
      /* High memory may be unavailable, try w/o OBJ_ANY */
      arc = DosAllocSharedMem((PPVOID)&gpData, SHAREDMEM_LIBCX, HEAP_SIZE,
                              PAG_READ | PAG_WRITE);
      TRACE("DosAllocSharedMem = %ld\n", arc);
    }

    ASSERT_MSG(arc == NO_ERROR, "%ld", arc);

    TRACE("gpData %p\n", gpData);

    /* Commit the initial block */
    arc = DosSetMem(gpData, HEAP_INIT_SIZE, PAG_DEFAULT | PAG_COMMIT);
    ASSERT_MSG(arc == NO_ERROR, "%ld", arc);

    gpData->size = HEAP_INIT_SIZE;

    /* Create shared heap */
    gpData->heap = _ucreate(gpData + 1, HEAP_INIT_SIZE - sizeof(*gpData),
                            _BLOCK_CLEAN, _HEAP_REGULAR | _HEAP_SHARED,
                            mem_alloc, NULL);
    TRACE("gpData->heap = %p\n", gpData->heap);
    ASSERT(gpData->heap);

    rc = _uopen(gpData->heap);
    ASSERT_MSG(rc == 0, "%d (%d)", rc, errno);

    gpData->refcnt = 1;

    /* Initialize common structures */
    GLOBAL_NEW_ARRAY(gpData->procs, PROC_DESC_HASH_SIZE);
    TRACE("gpData->procs = %p\n", gpData->procs);
    ASSERT(gpData->procs);

    GLOBAL_NEW_ARRAY(gpData->files, FILE_DESC_HASH_SIZE);
    TRACE("gpData->files = %p\n", gpData->files);
    ASSERT(gpData->files);

    break;
  }

  /*
   * Perform common initialization (both for the first and ordinary processes).
   */

  /* Make sure a process description for this process is created */
  ProcDesc *proc = get_proc_desc(getpid());
  ASSERT(proc);

  /* Initialize individual components */
  mmap_init(proc);
  fcntl_locking_init(proc);

  /* Check if it's a spawn2 wrapper (e.g. spawn2-wrapper.c) */
  {
    char dll[CCHMAXPATH + sizeof(SPAWN2_WRAPPERNAME) + 1];
    if (get_module_name(dll, sizeof(dll)))
    {
      strcpy(_getname(dll), SPAWN2_WRAPPERNAME);

      char exe[CCHMAXPATH + 1];
      if (_execname(exe, sizeof(exe)) == 0 && stricmp(dll, exe) == 0)
      {
        proc->flags |= Proc_Spawn2Wrapper;
        TRACE("spawn2 wrapper\n");

        /* Make sure the semaphore is available (needed for spawn2-wrapper.c) */
        ASSERT(gpData->spawn2_sem);
        global_spawn2_sem(proc);
      }
    }
  }

  DosReleaseMutexSem(gMutex);

  TRACE("done\n");
}