Esempio n. 1
0
/*===========================================================================*
 *				test_mutex				     *
 *===========================================================================*/
static void test_mutex(void)
{
  unsigned int i;
  thread_t t[3];
#ifdef MDEBUG
  mthread_verify();
#endif
  if (mthread_mutex_init(&mu[0], NULL) != 0) err(2, 1);
  if (mthread_mutex_init(&mu[1], NULL) != 0) err(2, 2);
  if (mthread_mutex_init(&mu[2], NULL) != 0) err(2, 3);

  if (mthread_create(&t[0], NULL, mutex_a, (void *) mu) != 0) err(2, 3);
  if (mthread_create(&t[1], NULL, mutex_b, (void *) mu) != 0) err(2, 4);
  if (mthread_create(&t[2], NULL, mutex_c, (void *) mu) != 0) err(2, 5);

  if (mthread_mutex_lock(&mu[2]) != 0) err(2, 6);

  mthread_yield_all(); /* Should result in a RUNNABLE mutex_a, and a blocked
  			* on mutex mutex_b and mutex_c.
  			*/ 

  VERIFY_MUTEX(1, 0, 0, 2, 7); /* err(2, 7) */
  if (mthread_mutex_unlock(&mu[2]) != 0) err(2, 8);

  mthread_yield();	/* Should schedule mutex_a to release the lock on the
			 * mu[0] mutex. Consequently allowing mutex_b and mutex_c
  			* to acquire locks on the mutexes and exit.
  			*/
  VERIFY_MUTEX(2, 0, 0, 2, 9);

  for (i = 0; i < (sizeof(t) / sizeof(thread_t)); i++) 
	if (mthread_join(t[i], NULL) != 0) err(2, 10);

  if (mthread_mutex_destroy(&mu[0]) != 0) err(2, 11);
  if (mthread_mutex_destroy(&mu[1]) != 0) err(2, 12);
  if (mthread_mutex_destroy(&mu[2]) != 0) err(2, 13);

#ifdef MDEBUG
  mthread_verify();
#endif
}
Esempio n. 2
0
/*===========================================================================*
 *				test_attributes				     *
 *===========================================================================*/
static void test_attributes(void)
{
  attr_t tattr;
  thread_t tid;
  int detachstate = -1, status = 0;
  unsigned int i, no_ints, stack_untouched = 1;
  void *stackaddr, *newstackaddr;
  int *stackp;
  size_t stacksize, newstacksize;

#ifdef MDEBUG
  mthread_verify();
#endif

  /* Initialize thread attribute and try to read the default values */
  if (mthread_attr_init(&tattr) != 0) err(11, 1);
  if (mthread_attr_getdetachstate(&tattr, &detachstate) != 0) err(11, 2);
  if (detachstate != MTHREAD_CREATE_JOINABLE) err(11, 3);
  if (mthread_attr_getstack(&tattr, &stackaddr, &stacksize) != 0) err(11, 4);
  if (stackaddr != NULL) err(11, 5);
  if (stacksize != (size_t) 0) err(11, 6);

  /* Modify the attribute ... */
  /* Try bogus detach state value */
  if (mthread_attr_setdetachstate(&tattr, 0xc0ffee) == 0) err(11, 7);
  if (mthread_attr_setdetachstate(&tattr, MTHREAD_CREATE_DETACHED) != 0)
  	err(11, 8);
  newstacksize = (size_t) MEG;
  if ((newstackaddr = malloc(newstacksize)) == NULL) err(11, 9);
  if (mthread_attr_setstack(&tattr, newstackaddr, newstacksize) != 0)
  	err(11, 10);
   /* ... and read back the new values. */
  if (mthread_attr_getdetachstate(&tattr, &detachstate) != 0) err(11, 11);
  if (detachstate != MTHREAD_CREATE_DETACHED) err(11, 12);
  if (mthread_attr_getstack(&tattr, &stackaddr, &stacksize) != 0) err(11, 13);
  if (stackaddr != newstackaddr) err(11, 14);
  if (stacksize != newstacksize) err(11, 15);
  if (mthread_attr_destroy(&tattr) != 0) err(11, 16);
  free(newstackaddr);

  /* Try to allocate too small a stack; it should fail and the attribute 
   * values should remain as is.
   */
  newstacksize = MTHREAD_STACK_MIN - 1;
  stackaddr = NULL;
  stacksize = 0;
  if (mthread_attr_init(&tattr) != 0) err(11, 17);
  if ((newstackaddr = malloc(newstacksize)) == NULL) err(11, 18);
  if (mthread_attr_setstack(&tattr, newstackaddr, newstacksize) != EINVAL)
  	err(11, 19);
  if (mthread_attr_getstack(&tattr, &stackaddr, &stacksize) != 0) err(11, 21);
  if (stackaddr == newstackaddr) err(11, 22);
  if (stacksize == newstacksize) err(11, 23);
  if (mthread_attr_destroy(&tattr) != 0) err(11, 24);
  free(newstackaddr);

  /* Tell attribute to let the system allocate a stack for the thread and only
   * dictate how big that stack should be (2 megabyte, not actually allocated
   * yet).
   */
  if (mthread_attr_init(&tattr) != 0) err(11, 25);
  if (mthread_attr_setstack(&tattr, NULL /* System allocated */, 2*MEG) != 0)
  	err(11, 26);
  if (mthread_attr_getstack(&tattr, &stackaddr, &stacksize) != 0) err(11, 27);
  if (stackaddr != NULL) err(11, 28);
  if (stacksize != 2*MEG) err(11, 29);

  /* Use set/getstacksize to set and retrieve new stack sizes */
  stacksize = 0;
  if (mthread_attr_getstacksize(&tattr, &stacksize) != 0) err(11, 30);
  if (stacksize != 2*MEG) err(11, 31);
  newstacksize = MEG;
  if (mthread_attr_setstacksize(&tattr, newstacksize) != 0) err(11, 32);
  if (mthread_attr_getstacksize(&tattr, &stacksize) != 0) err(11, 33);
  if (stacksize != newstacksize) err(11, 34);
  if (mthread_attr_destroy(&tattr) != 0) err(11, 35);

  /* Perform same tests, but also actually use them in a thread */
  if (mthread_attr_init(&tattr) != 0) err(11, 36);
  if (mthread_attr_setdetachstate(&tattr, MTHREAD_CREATE_DETACHED) != 0)
  	err(11, 37);
  condition_mutex = &mu[0];
  if (mthread_mutex_init(condition_mutex, NULL) != 0) err(11, 38);
  if (mthread_cond_init(&condition, NULL) != 0) err(11, 39);
  if (mthread_mutex_lock(condition_mutex) != 0) err(11, 40);
  if (mthread_create(&tid, &tattr, thread_f, NULL) != 0) err(11, 41);
  /* Wait for thread_f to finish */
  if (mthread_cond_wait(&condition, condition_mutex) != 0) err(11, 42);
  if (mthread_mutex_unlock(condition_mutex) != 0) err(11, 43);
  if (th_f != 1) err(11, 44);
  /* Joining a detached thread should fail */
  if (mthread_join(tid, NULL) == 0) err(11, 45);
  if (mthread_attr_destroy(&tattr) != 0) err(11, 46);

  /* Try telling the attribute how large the stack should be */
  if (mthread_attr_init(&tattr) != 0) err(11, 47);
  if (mthread_attr_setstack(&tattr, NULL, 2 * MTHREAD_STACK_MIN) != 0)
  	err(11, 48);
  if (mthread_mutex_lock(condition_mutex) != 0) err(11, 49);
  if (mthread_create(&tid, &tattr, thread_g, NULL) != 0) err(11, 50);
  /* Wait for thread_g to finish */
  if (mthread_cond_wait(&condition, condition_mutex) != 0) err(11, 51);
  if (mthread_mutex_unlock(condition_mutex) != 0) err(11, 52);
  if (th_g != 1) err(11, 53);
  if (mthread_attr_setdetachstate(&tattr, MTHREAD_CREATE_DETACHED) != 0)
  	err(11, 54); /* Shouldn't affect the join below, as thread is already
  		      * running as joinable. If this attribute should be 
  		      * modified after thread creation, use mthread_detach().
  		      */
  if (mthread_join(tid, NULL) != 0) err(11, 55);
  if (mthread_attr_destroy(&tattr) != 0) err(11, 56);

  /* Try telling the attribute how large the stack should be and where it is
   * located.
   */
  if (mthread_attr_init(&tattr) != 0) err(11, 57);
  stacksize = 3 * MEG;
  /* Make sure this test is meaningful. We have to verify that we actually
   * use a custom stack. So we're going to allocate an array on the stack in
   * thread_h that should at least be bigger than the default stack size
   * allocated by the system.
   */
  if (2 * MEG <= MTHREAD_STACK_MIN) err(11, 58);
  if ((stackaddr = malloc(stacksize)) == NULL) err(11, 59);
  /* Fill stack with pattern. We assume that the beginning of the stack
   * should be overwritten with something and that the end should remain
   * untouched. The thread will zero-fill around two-thirds of the stack with
   * zeroes, so we can check if that's true. 
   */
  stackp = stackaddr;
  no_ints = stacksize / sizeof(int);
  for (i = 0; i < no_ints ; i++) 
	stackp[i] = MAGIC;
  if (mthread_attr_setstack(&tattr, stackaddr, stacksize) != 0) err(11, 60);
  if (mthread_mutex_lock(condition_mutex) != 0) err(11, 61);
  if (mthread_create(&tid, &tattr, thread_h, (void *) &stacksize) != 0)	
  	err(11, 62);
  /* Wait for thread h to finish */
  if (mthread_cond_wait(&condition, condition_mutex) != 0) err(11, 63);
  if (th_h != 1) err(11, 64);
  if (mthread_mutex_unlock(condition_mutex) != 0) err(11, 65);

  /* Verify stack hypothesis; we assume a stack is used from the top and grows
   * downwards.
   */
#if (_MINIX_CHIP == _CHIP_INTEL)
  if (stackp[0] != MAGIC) err(11, 66); /* End of the stack */
  for (i = no_ints - 1 - 16; i < no_ints; i++)
  	if (stackp[i] != MAGIC) stack_untouched = 0;
  if (stack_untouched) err(11, 67); /* Beginning of the stack */
  if (stackp[no_ints / 2] != 0) err(11, 68);/*Zero half way through the stack*/
#else
#error "Unsupported chip for this test"
#endif

  if (mthread_join(tid, (void *) &status) != 0) err(11, 69);
  if ((size_t) status != stacksize) err(11, 70);
  if (mthread_attr_destroy(&tattr) != 0) err(11, 71); 
  if (mthread_mutex_destroy(condition_mutex) != 0) err(11, 72);
  if (mthread_cond_destroy(&condition) != 0) err(11, 73);
  free(stackaddr);

#ifdef MDEBUG
  mthread_verify();
#endif
}
Esempio n. 3
0
/*===========================================================================*
 *				test_condition				     *
 *===========================================================================*/
static void test_condition(void)
{
#define NTHREADS 10
  int i;
  thread_t t[2], s[NTHREADS];
  count_mutex = &mu[0];
  condition_mutex = &mu[1];

  /* Test simple condition variable behavior: Two threads increase a counter.
   * At some point one thread waits for a condition and the other thread
   * signals the condition. Consequently, one thread increased the counter a
   * few times less than other thread. Although the difference is 'random', 
   * there is a guaranteed minimum difference that we can measure.
   */

#ifdef MDEBUG
  mthread_verify();
#endif

  if (mthread_mutex_init(count_mutex, NULL) != 0) err(8, 1);
  if (mthread_mutex_init(condition_mutex, NULL) != 0) err(8, 2);
  if (mthread_cond_init(&condition, NULL) != 0) err(8, 3);
  count = 0;

  if (mthread_create(&t[0], NULL, cond_a, NULL) != 0) err(8, 4);
  if (mthread_create(&t[1], NULL, cond_b, NULL) != 0) err(8, 5);

  for (i = 0; i < (sizeof(t) / sizeof(thread_t)); i++)
	if (mthread_join(t[i], NULL) != 0) err(8, 6);

  if (mthread_mutex_destroy(count_mutex) != 0) err(8, 7);
  if (mthread_mutex_destroy(condition_mutex) != 0) err(8, 8);
  if (mthread_cond_destroy(&condition) != 0) err(8, 9);

#ifdef MTHREAD_STRICT
  /* Let's try to destroy it again. Should fails as it's uninitialized. */
  /* Note: this only works when libmthread is compiled with MTHREAD_STRICT. In
   * POSIX this situation is a MAY fail if... */
  if (mthread_cond_destroy(&condition) == 0) err(8, 10); 
#endif

#ifdef MDEBUG
  mthread_verify();
#endif

  /* Test signal broadcasting: spawn N threads that will increase a counter
   * after a condition has been signaled. The counter must equal N. */
  if (mthread_mutex_init(count_mutex, NULL) != 0) err(8, 11);
  if (mthread_mutex_init(condition_mutex, NULL) != 0) err(8, 12);
  if (mthread_cond_init(&condition, NULL) != 0) err(8, 13);
  condition_met = count = 0;

  for (i = 0; i < NTHREADS; i++) 
	if (mthread_create(&s[i], NULL, cond_broadcast, NULL) != 0) err(8, 14);

  /* Allow other threads to block on the condition variable. If we don't yield,
   * the threads will only start running when we call mthread_join below. In
   * that case the while loop in cond_broadcast will never evaluate to true.
   */
  mthread_yield();

  if (mthread_mutex_lock(condition_mutex) != 0) err(8, 15);
  condition_met = 1;
  if (mthread_cond_broadcast(&condition) != 0) err(8, 16);
  if (mthread_mutex_unlock(condition_mutex) != 0) err(8, 17);

  for (i = 0; i < (sizeof(s) / sizeof(thread_t)); i++) 
	if (mthread_join(s[i], NULL) != 0) err(8, 18);

  if (count != NTHREADS) err(8, 19);
  if (mthread_mutex_destroy(count_mutex) != 0) err(8, 20);
  if (mthread_mutex_destroy(condition_mutex) != 0) err(8, 21);
  if (mthread_cond_destroy(&condition) != 0) err(8, 22); 

#ifdef MTHREAD_STRICT 
  /* Again, destroying the condition variable twice shouldn't work */
  /* See previous note about MTHREAD_STRICT */
  if (mthread_cond_destroy(&condition) == 0) err(8, 23); 
#endif

#ifdef MDEBUG
  mthread_verify();
#endif
}
Esempio n. 4
0
File: main.c Progetto: Sciumo/minix
/*===========================================================================*
 *				sef_cb_init_fresh			     *
 *===========================================================================*/
static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
{
/* Initialize the virtual file server. */
  int s, i;
  struct fproc *rfp;
  message mess;
  struct rprocpub rprocpub[NR_BOOT_PROCS];

  force_sync = 0;
  receive_from = ANY;
  self = NULL;
  verbose = 0;

  /* Initialize proc endpoints to NONE */
  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
	rfp->fp_endpoint = NONE;
	rfp->fp_pid = PID_FREE;
  }

  /* Initialize the process table with help of the process manager messages.
   * Expect one message for each system process with its slot number and pid.
   * When no more processes follow, the magic process number NONE is sent.
   * Then, stop and synchronize with the PM.
   */
  do {
	if ((s = sef_receive(PM_PROC_NR, &mess)) != OK)
		panic("VFS: couldn't receive from PM: %d", s);

	if (mess.m_type != PM_INIT)
		panic("unexpected message from PM: %d", mess.m_type);

	if (NONE == mess.PM_PROC) break;

	rfp = &fproc[mess.PM_SLOT];
	rfp->fp_flags = FP_NOFLAGS;
	rfp->fp_pid = mess.PM_PID;
	rfp->fp_endpoint = mess.PM_PROC;
	rfp->fp_grant = GRANT_INVALID;
	rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
	rfp->fp_realuid = (uid_t) SYS_UID;
	rfp->fp_effuid = (uid_t) SYS_UID;
	rfp->fp_realgid = (gid_t) SYS_GID;
	rfp->fp_effgid = (gid_t) SYS_GID;
	rfp->fp_umask = ~0;
  } while (TRUE);			/* continue until process NONE */
  mess.m_type = OK;			/* tell PM that we succeeded */
  s = send(PM_PROC_NR, &mess);		/* send synchronization message */

  /* All process table entries have been set. Continue with initialization. */
  fp = &fproc[_ENDPOINT_P(VFS_PROC_NR)];/* During init all communication with
					 * FSes is on behalf of myself */
  init_dmap();			/* Initialize device table. */
  system_hz = sys_hz();

  /* Map all the services in the boot image. */
  if ((s = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
			    (vir_bytes) rprocpub, sizeof(rprocpub), S)) != OK){
	panic("sys_safecopyfrom failed: %d", s);
  }
  for (i = 0; i < NR_BOOT_PROCS; i++) {
	if (rprocpub[i].in_use) {
		if ((s = map_service(&rprocpub[i])) != OK) {
			panic("VFS: unable to map service: %d", s);
		}
	}
  }

  /* Subscribe to block and character driver events. */
  s = ds_subscribe("drv\\.[bc]..\\..*", DSF_INITIAL | DSF_OVERWRITE);
  if (s != OK) panic("VFS: can't subscribe to driver events (%d)", s);

  /* Initialize worker threads */
  for (i = 0; i < NR_WTHREADS; i++)  {
	worker_init(&workers[i]);
  }
  worker_init(&sys_worker); /* exclusive system worker thread */
  worker_init(&dl_worker); /* exclusive worker thread to resolve deadlocks */

  /* Initialize global locks */
  if (mthread_mutex_init(&pm_lock, NULL) != 0)
	panic("VFS: couldn't initialize pm lock mutex");
  if (mthread_mutex_init(&exec_lock, NULL) != 0)
	panic("VFS: couldn't initialize exec lock");
  if (mthread_mutex_init(&bsf_lock, NULL) != 0)
	panic("VFS: couldn't initialize block special file lock");

  /* Initialize event resources for boot procs and locks for all procs */
  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
	if (mutex_init(&rfp->fp_lock, NULL) != 0)
		panic("unable to initialize fproc lock");
#if LOCK_DEBUG
	rfp->fp_vp_rdlocks = 0;
	rfp->fp_vmnt_rdlocks = 0;
#endif
  }

  init_vnodes();		/* init vnodes */
  init_vmnts();			/* init vmnt structures */
  init_select();		/* init select() structures */
  init_filps();			/* Init filp structures */
  mount_pfs();			/* mount Pipe File Server */
  worker_start(do_init_root);	/* mount initial ramdisk as file system root */
  yield();			/* force do_init_root to start */
  self = NULL;

  return(OK);
}
Esempio n. 5
0
/*===========================================================================*
 *				sef_cb_init_fresh			     *
 *===========================================================================*/
static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
{
/* Initialize the virtual file server. */
  int s, i;
  struct fproc *rfp;
  message mess;
  struct rprocpub rprocpub[NR_BOOT_PROCS];

  self = NULL;
  verbose = 0;

  /* Initialize proc endpoints to NONE */
  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
	rfp->fp_endpoint = NONE;
	rfp->fp_pid = PID_FREE;
  }

  /* Initialize the process table with help of the process manager messages.
   * Expect one message for each system process with its slot number and pid.
   * When no more processes follow, the magic process number NONE is sent.
   * Then, stop and synchronize with the PM.
   */
  do {
	if ((s = sef_receive(PM_PROC_NR, &mess)) != OK)
		panic("VFS: couldn't receive from PM: %d", s);

	if (mess.m_type != VFS_PM_INIT)
		panic("unexpected message from PM: %d", mess.m_type);

	if (NONE == mess.VFS_PM_ENDPT) break;

	rfp = &fproc[mess.VFS_PM_SLOT];
	rfp->fp_flags = FP_NOFLAGS;
	rfp->fp_pid = mess.VFS_PM_PID;
	rfp->fp_endpoint = mess.VFS_PM_ENDPT;
	rfp->fp_grant = GRANT_INVALID;
	rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
	rfp->fp_realuid = (uid_t) SYS_UID;
	rfp->fp_effuid = (uid_t) SYS_UID;
	rfp->fp_realgid = (gid_t) SYS_GID;
	rfp->fp_effgid = (gid_t) SYS_GID;
	rfp->fp_umask = ~0;
  } while (TRUE);			/* continue until process NONE */
  mess.m_type = OK;			/* tell PM that we succeeded */
  s = ipc_send(PM_PROC_NR, &mess);		/* send synchronization message */

  system_hz = sys_hz();

  /* Subscribe to block and character driver events. */
  s = ds_subscribe("drv\\.[bc]..\\..*", DSF_INITIAL | DSF_OVERWRITE);
  if (s != OK) panic("VFS: can't subscribe to driver events (%d)", s);

  /* Initialize worker threads */
  worker_init();

  /* Initialize global locks */
  if (mthread_mutex_init(&bsf_lock, NULL) != 0)
	panic("VFS: couldn't initialize block special file lock");

  init_dmap();			/* Initialize device table. */

  /* Map all the services in the boot image. */
  if ((s = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
			    (vir_bytes) rprocpub, sizeof(rprocpub))) != OK){
	panic("sys_safecopyfrom failed: %d", s);
  }
  for (i = 0; i < NR_BOOT_PROCS; i++) {
	if (rprocpub[i].in_use) {
		if ((s = map_service(&rprocpub[i])) != OK) {
			panic("VFS: unable to map service: %d", s);
		}
	}
  }

  /* Initialize locks and initial values for all processes. */
  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
	if (mutex_init(&rfp->fp_lock, NULL) != 0)
		panic("unable to initialize fproc lock");
	rfp->fp_worker = NULL;
#if LOCK_DEBUG
	rfp->fp_vp_rdlocks = 0;
	rfp->fp_vmnt_rdlocks = 0;
#endif

	/* Initialize process directories. mount_fs will set them to the
	 * correct values.
	 */
	for (i = 0; i < OPEN_MAX; i++)
		rfp->fp_filp[i] = NULL;
	rfp->fp_rd = NULL;
	rfp->fp_wd = NULL;
  }

  init_vnodes();		/* init vnodes */
  init_vmnts();			/* init vmnt structures */
  init_select();		/* init select() structures */
  init_filps();			/* Init filp structures */

  /* Mount PFS and initial file system root. */
  worker_start(fproc_addr(VFS_PROC_NR), do_init_root, &mess /*unused*/,
	FALSE /*use_spare*/);

  return(OK);
}