示例#1
0
文件: kernel.c 项目: jdekozak/coprthr
void __do_create_kernel(cl_kernel krn, cl_uint k) 
{
	int i;
	void* p;

	cl_program prg = krn->prg;

	DEBUG(__FILE__,__LINE__,"__do_create_kernel: knum=%d",k);

	krn->name = prg->imp.kname[k];

	DEBUG(__FILE__,__LINE__,"__do_create_kernel: kname=%s",krn->name);

/* XXX this is odd way of assigning kernel, fix it by contracting v_* -DAR */

	krn->imp.v_kbin = prg->imp.v_kbin;
	krn->imp.v_ksym = prg->imp.v_ksym;
	krn->imp.v_kcall = prg->imp.v_kcall;
	krn->imp.knum = k;

	cl_uint narg = krn->narg = prg->imp.knarg[k];

	DEBUG(__FILE__,__LINE__,"__do_create_kernel: narg=%d",narg);

	if (narg == 0) return;

	if (prg->imp.karg_kind[k]) 
		__clone(krn->imp.arg_kind,prg->imp.karg_kind[k],narg,cl_uint);
	else krn->imp.arg_kind = (cl_uint*)malloc(narg*sizeof(cl_uint));

	if (prg->imp.karg_sz[k]) 
		__clone(krn->imp.arg_sz,prg->imp.karg_sz[k],narg,size_t);
	else krn->imp.arg_sz = (size_t*)malloc(narg*sizeof(size_t));

	krn->imp.arg_vec = malloc(narg*sizeof(void*));
		
	size_t arg_buf_sz = krn->imp.arg_buf_sz = prg->imp.karg_buf_sz[k];

	if (arg_buf_sz > 0) krn->imp.arg_buf = p = malloc(arg_buf_sz);

	for(i=0;i<narg;i++) {
		krn->imp.arg_vec[i] = p;
		p += krn->imp.arg_sz[i];
		DEBUG(__FILE__,__LINE__,"CHECKING arg_sz[%d] %d",i,krn->imp.arg_sz[i]);
	}

	/* XXX paranoid check, remove after testing -DAR */	
	if ((intptr_t)p-(intptr_t)krn->imp.arg_buf != krn->imp.arg_buf_sz) {
		ERROR(__FILE__,__LINE__,"internal error");
		exit(-1);
	}
		
}
示例#2
0
/* Create a new thread. It should be passed "fcn", a function which
 * takes two arguments, (the second one is a dummy, always 4). The
 * first argument is passed in "arg". Returns the TID of the new
 * thread */
static pid_t
create_thread(int (*fcn)(void *), void *arg, void **stack)
{
    pid_t newpid; 
    int flags;
    void *my_stack;
    
    my_stack = stack_alloc(THREAD_STACK_SIZE);
    /* need SIGCHLD so parent will get that signal when child dies,
     * else have errors doing a wait */
    flags = SIGCHLD | CLONE_THREAD | CLONE_VM |
        /* CLONE_THREAD => no signal to parent on termination; have to use
         * CLONE_CHILD_CLEARTID to get that.  Since we're using library call
         * instead of raw system call we don't have child_tidptr argument,
         * so we set the location in the child itself via set_tid_address(). */
        CLONE_CHILD_CLEARTID | 
        CLONE_FS | CLONE_FILES | CLONE_SIGHAND;
    newpid = __clone(fcn, my_stack, flags, arg);
    /* this is really a tid since we passed CLONE_THREAD: child has same pid as us */
  
    if (newpid == -1) {
        fprintf(stderr, "smp.c: Error calling __clone\n");
        stack_free(my_stack, THREAD_STACK_SIZE);
        return -1;
    }

    *stack = my_stack;
    return newpid;
}
示例#3
0
static int pthread_initialize_manager(void)
{
	int manager_pipe[2];

	/* Setup stack for thread manager */
	__pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
	if (__pthread_manager_thread_bos == NULL) 
		return -1;
	
	pthread_manager_thread_tos =
		__pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;
    /* Setup pipe to communicate with thread manager */
	if (pipe(manager_pipe) == -1) {
		free(__pthread_manager_thread_bos);
		return -1;
    }
	__pthread_manager_request = manager_pipe[1]; /* writing end */
	__pthread_manager_reader = manager_pipe[0]; /* reading end */
	/* Start the thread manager */
	if (__clone(__pthread_manager,
	          	__pthread_manager_thread_tos,
				CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
				(void *)(long)manager_pipe[0]) == -1) {
		free(__pthread_manager_thread_bos);
		__libc_close(manager_pipe[0]);
    	__libc_close(manager_pipe[1]);
	    __pthread_manager_request = -1;
		return -1;
	}
	return 0;
}
示例#4
0
文件: ulib.c 项目: TySag/project
int clone(uint32_t clone_flags, uintptr_t stack, int (*fn) (void *), void *arg)
{
	int ret;
	lock_fork();
	ret = __clone(clone_flags, stack, fn, arg);
	unlock_fork();
	return ret;
}
示例#5
0
static struct native_property * __clone (
    struct native_property * prop,
    CMPIStatus * rc )
{
    struct native_property * result;
    CMPIStatus tmp;

    if (prop == NULL)
    {

        CMSetStatus ( rc, CMPI_RC_OK );
        return NULL;
    }

    result =
        (struct native_property * )
        tool_mm_alloc ( TOOL_MM_NO_ADD,
                        sizeof ( struct native_property ) );

    result->name  = strdup ( prop->name );
    result->origin = prop->origin ? strdup(prop->origin) : 0;
    result->type  = prop->type;
    result->state = prop->state;
    result->value = native_clone_CMPIValue ( prop->type,
                    &prop->value,
                    &tmp );

    if (tmp.rc != CMPI_RC_OK)
    {

        result->state = CMPI_nullValue;
    }

    result->next  = __clone ( prop->next, rc );
    return result;
}
示例#6
0
int main(int argc, char *argv[])
{
	int c;
	int clone_err;
	int i,rc;
	int exit_rc = 0;
	int wait_status;
	int iterations = 0;
	struct sched_param param;
	struct rlimit myrlimit;
	struct sembuf mysembuf1;

	num_active = num_children ; /* In case its unspecified */

	while ((c = getopt(argc, argv, "c:t:a:w:r:o:q")) != -1) {
	  switch (c) {
	  case 'c': num_children = atoi(optarg); break;
	  case 't': num_seconds = atoi(optarg); break;
	  case 'a': num_active = atoi(optarg); break;
	  case 'w': weight_reschedule_idle = atoi(optarg); break;
	  case 'r': rnd_compute_time = atoi(optarg); break; 	  
	  case 'o': foutput = atoi(optarg); break;
	  case 'q': fquiet = 1; break;
	  default:  usage();
	    goto exit_main2;
	  }
	}


	
	
	if ((num_seconds <= 0) ||
	    (num_children <= 0) || (num_children > MAX_CHILDREN) ||
	    (num_active <= 0) || (num_active > num_children) ||
	    (weight_reschedule_idle < 0) || (weight_reschedule_idle > 100) ||
	    (rnd_compute_time < 0)
	   )
	    
	{
	    	usage();
		goto exit_main2;
	}
	

	/* Increase limits on number of open files */
	/* normally 1024 (cur & max), set to MAX_CHILDREN */

	myrlimit.rlim_cur = myrlimit.rlim_max = MAX_CHILDREN*2 ; 

	if (setrlimit(RLIMIT_NOFILE,&myrlimit) != 0) {
		exit_rc = errno ;
		perror("setrlimit() ");
		goto exit_main2;
	}
	
	/* allocate childrens stacks*/
	
	child_stack = malloc(num_children*STACK_SIZE);
	if (child_stack == NULL) {
		exit_rc = errno;
		perror ("malloc of 'child_stack' failed ");
		goto exit_main2;
	}
	
	/* open num_children pipes */
	for (i=0; i< num_children; i++) {
		if (pipe(childpipe[i]) < 0) {
			exit_rc = errno;
			perror ("pipe() ");
			goto exit_main3;
		}
	}

        /* calibrate internal loops */
	calibration();
	probyield = local_exec_count ;
	TOKENSZ = sizeof(char); 
	probyield = (100.0-(double)weight_reschedule_idle)/100.0 ; 
	probyieldmult = probyield / ((1-probyield)*(1-probyield)); 

	
	/*
	comp_nonyield_rounds = (int) (uniform(rnd_compute_time) * rounds_per_microsecond) ;
	comp_yield_rounds = (int) (comp_nonyield_rounds * probyieldmult) ; 
	printf("Sample subrounds : nonyield %d yield %d, probyield %0.3f\n",
	   comp_nonyield_rounds, comp_yield_rounds, probyield); 
	*/

	/* start_sem is used to start all children at same time */	

	start_sem = semget (IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0660);
	if (start_sem == -1) {
		exit_rc = errno;
		perror("semget(start_sem) IPC_CREATE ");
		goto exit_main4;
	}
	
	/* allocate/initialize statistic variables */
	
	total = malloc(num_children*sizeof(struct _total));
	if (total == NULL) {
		exit_rc = errno;
		perror ("malloc of 'total' failed ");
		goto exit_main3;
	}
	for (i = 0 ; i < num_children ; i++)
		total[i].count = 0;


	/* Launch threads */
  	worker = bouncer;
	for (i=0; i< num_children; i++) {
		clone_err = __clone(worker, 
				    &child_stack[(i+1)*STACK_SIZE],
				    CLONE_FLAGS,
				    (void*)i);
		if (clone_err == -1) {
			exit_rc = errno;
			perror ("clone() ");
			goto exit_main5;
		}
		// printf("\t\tLaunched child %d\n",i);

	}

	/* Increase priority of parent thread */

	param.sched_priority = 90;
	rc = sched_setscheduler(getpid(), SCHED_FIFO, &param);
	if (rc == -1) {
		exit_rc = errno;
		perror ("sched_setscheduler() ");
		goto exit_main5;
	}

	run_test_time();
	

exit_main5: 
	/* wait until all children complete */	
	for (i = 0 ; i < num_children ; i++) {
		rc = waitpid (-1, &wait_status, __WCLONE);
		if (rc == -1) {
			exit_rc = errno;
			perror ("waitpid() ");
		}
	}

exit_main4:
 
	rc = semctl(start_sem, 0, IPC_RMID, 0);

exit_main3:

	/* explicitly close all pipes : unnecessary */
	for (i=0; i< num_children; i++) {
		close(childpipe[i][0]);
		close(childpipe[i][1]);
	}
	free(child_stack);
	
exit_main2:
	return (exit_rc) ;
}
示例#7
0
static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
				 void * (*start_routine)(void *), void *arg,
				 sigset_t * mask, int father_pid,
				 int report_events,
				 td_thr_events_t *event_maskp)
{
  size_t sseg;
  int pid;
  pthread_descr new_thread;
  char *stack_addr;
  char * new_thread_bottom;
  pthread_t new_thread_id;
  char *guardaddr = NULL;
  size_t guardsize = 0, stksize = 0;
  int pagesize = __getpagesize();
  int saved_errno = 0;

#ifdef USE_TLS
  new_thread = _dl_allocate_tls (NULL);
  if (new_thread == NULL)
    return EAGAIN;
# if TLS_DTV_AT_TP
  /* pthread_descr is below TP.  */
  new_thread = (pthread_descr) ((char *) new_thread - TLS_PRE_TCB_SIZE);
# endif
#else
  /* Prevent warnings.  */
  new_thread = NULL;
#endif

  /* First check whether we have to change the policy and if yes, whether
     we can  do this.  Normally this should be done by examining the
     return value of the __sched_setscheduler call in pthread_start_thread
     but this is hard to implement.  FIXME  */
  if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0)
    return EPERM;
  /* Find a free segment for the thread, and allocate a stack if needed */
  for (sseg = 2; ; sseg++)
    {
      if (sseg >= PTHREAD_THREADS_MAX)
	{
#ifdef USE_TLS
# if TLS_DTV_AT_TP
	  new_thread = (pthread_descr) ((char *) new_thread + TLS_PRE_TCB_SIZE);
# endif
	  _dl_deallocate_tls (new_thread, true);
#endif
	  return EAGAIN;
	}
      if (__pthread_handles[sseg].h_descr != NULL)
	continue;
      if (pthread_allocate_stack(attr, thread_segment(sseg),
				 pagesize, &stack_addr, &new_thread_bottom,
                                 &guardaddr, &guardsize, &stksize) == 0)
	{
#ifdef USE_TLS
	  new_thread->p_stackaddr = stack_addr;
#else
	  new_thread = (pthread_descr) stack_addr;
#endif
	  break;
#ifndef __ARCH_USE_MMU__
	} else {
	  /* When there is MMU, mmap () is used to allocate the stack. If one
	   * segment is already mapped, we should continue to see if we can
	   * use the next one. However, when there is no MMU, malloc () is used.
	   * It's waste of CPU cycles to continue to try if it fails.  */
	  return EAGAIN;
#endif
	}
    }
  __pthread_handles_num++;
  /* Allocate new thread identifier */
  pthread_threads_counter += PTHREAD_THREADS_MAX;
  new_thread_id = sseg + pthread_threads_counter;
  /* Initialize the thread descriptor.  Elements which have to be
     initialized to zero already have this value.  */
#if !defined USE_TLS || !TLS_DTV_AT_TP
  new_thread->p_header.data.tcb = new_thread;
  new_thread->p_header.data.self = new_thread;
#endif
#if TLS_MULTIPLE_THREADS_IN_TCB || !defined USE_TLS || !TLS_DTV_AT_TP
  new_thread->p_multiple_threads = 1;
#endif
  new_thread->p_tid = new_thread_id;
  new_thread->p_lock = &(__pthread_handles[sseg].h_lock);
  new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
  new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
#if !(USE_TLS && HAVE___THREAD)
  new_thread->p_errnop = &new_thread->p_errno;
  new_thread->p_h_errnop = &new_thread->p_h_errno;
  new_thread->p_resp = &new_thread->p_res;
#endif
  new_thread->p_guardaddr = guardaddr;
  new_thread->p_guardsize = guardsize;
  new_thread->p_nr = sseg;
  new_thread->p_inheritsched = attr ? attr->__inheritsched : 0;
  new_thread->p_alloca_cutoff = stksize / 4 > __MAX_ALLOCA_CUTOFF
				 ? __MAX_ALLOCA_CUTOFF : stksize / 4;
  /* Initialize the thread handle */
  __pthread_init_lock(&__pthread_handles[sseg].h_lock);
  __pthread_handles[sseg].h_descr = new_thread;
  __pthread_handles[sseg].h_bottom = new_thread_bottom;
  /* Determine scheduling parameters for the thread */
  new_thread->p_start_args.schedpolicy = -1;
  if (attr != NULL) {
    new_thread->p_detached = attr->__detachstate;
    new_thread->p_userstack = attr->__stackaddr_set;

    switch(attr->__inheritsched) {
    case PTHREAD_EXPLICIT_SCHED:
      new_thread->p_start_args.schedpolicy = attr->__schedpolicy;
      memcpy (&new_thread->p_start_args.schedparam, &attr->__schedparam,
	      sizeof (struct sched_param));
      break;
    case PTHREAD_INHERIT_SCHED:
      new_thread->p_start_args.schedpolicy = __sched_getscheduler(father_pid);
      __sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
      break;
    }
    new_thread->p_priority =
      new_thread->p_start_args.schedparam.sched_priority;
  }
  /* Finish setting up arguments to pthread_start_thread */
  new_thread->p_start_args.start_routine = start_routine;
  new_thread->p_start_args.arg = arg;
  new_thread->p_start_args.mask = *mask;
  /* Make the new thread ID available already now.  If any of the later
     functions fail we return an error value and the caller must not use
     the stored thread ID.  */
  *thread = new_thread_id;
  /* Raise priority of thread manager if needed */
  __pthread_manager_adjust_prio(new_thread->p_priority);
  /* Do the cloning.  We have to use two different functions depending
     on whether we are debugging or not.  */
  pid = 0;	/* Note that the thread never can have PID zero.  */
  if (report_events)
    {
      /* See whether the TD_CREATE event bit is set in any of the
         masks.  */
      int idx = __td_eventword (TD_CREATE);
      uint32_t mask = __td_eventmask (TD_CREATE);

      if ((mask & (__pthread_threads_events.event_bits[idx]
		   | event_maskp->event_bits[idx])) != 0)
	{
	  /* Lock the mutex the child will use now so that it will stop.  */
	  __pthread_lock(new_thread->p_lock, NULL);

	  /* We have to report this event.  */
#ifdef NEED_SEPARATE_REGISTER_STACK
	  /* Perhaps this version should be used on all platforms. But
	   this requires that __clone2 be uniformly supported
	   everywhere.

	   And there is some argument for changing the __clone2
	   interface to pass sp and bsp instead, making it more IA64
	   specific, but allowing stacks to grow outward from each
	   other, to get less paging and fewer mmaps.  */
	  pid = __clone2(pthread_start_thread_event,
  		 (void **)new_thread_bottom,
			 (char *)stack_addr - new_thread_bottom,
			 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
			 __pthread_sig_cancel, new_thread);
#elif _STACK_GROWS_UP
	  pid = __clone(pthread_start_thread_event, (void *) new_thread_bottom,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
			__pthread_sig_cancel, new_thread);
#else
	  pid = __clone(pthread_start_thread_event, stack_addr,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
			__pthread_sig_cancel, new_thread);
#endif
	  saved_errno = errno;
	  if (pid != -1)
	    {
	      /* Now fill in the information about the new thread in
		 the newly created thread's data structure.  We cannot let
		 the new thread do this since we don't know whether it was
		 already scheduled when we send the event.  */
	      new_thread->p_eventbuf.eventdata = new_thread;
	      new_thread->p_eventbuf.eventnum = TD_CREATE;
	      __pthread_last_event = new_thread;

	      /* We have to set the PID here since the callback function
		 in the debug library will need it and we cannot guarantee
		 the child got scheduled before the debugger.  */
	      new_thread->p_pid = pid;

	      /* Now call the function which signals the event.  */
	      __linuxthreads_create_event ();

	      /* Now restart the thread.  */
	      __pthread_unlock(new_thread->p_lock);
	    }
	}
    }
  if (pid == 0)
    {
#ifdef NEED_SEPARATE_REGISTER_STACK
      pid = __clone2(pthread_start_thread,
		     (void **)new_thread_bottom,
                     (char *)stack_addr - new_thread_bottom,
		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
		     __pthread_sig_cancel, new_thread);
#elif _STACK_GROWS_UP
      pid = __clone(pthread_start_thread, (void *) new_thread_bottom,
		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
		    __pthread_sig_cancel, new_thread);
#else
      pid = __clone(pthread_start_thread, stack_addr,
		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM |
		    __pthread_sig_cancel, new_thread);
#endif /* !NEED_SEPARATE_REGISTER_STACK */
      saved_errno = errno;
    }
  /* Check if cloning succeeded */
  if (pid == -1) {
    /* Free the stack if we allocated it */
    if (attr == NULL || !attr->__stackaddr_set)
      {
#ifdef NEED_SEPARATE_REGISTER_STACK
	size_t stacksize = ((char *)(new_thread->p_guardaddr)
			    - new_thread_bottom);
	munmap((caddr_t)new_thread_bottom,
	       2 * stacksize + new_thread->p_guardsize);
#elif _STACK_GROWS_UP
# ifdef USE_TLS
	size_t stacksize = guardaddr - stack_addr;
	munmap(stack_addr, stacksize + guardsize);
# else
	size_t stacksize = guardaddr - (char *)new_thread;
	munmap(new_thread, stacksize + guardsize);
# endif
#else
# ifdef USE_TLS
	size_t stacksize = stack_addr - new_thread_bottom;
# else
	size_t stacksize = (char *)(new_thread+1) - new_thread_bottom;
# endif
	munmap(new_thread_bottom - guardsize, guardsize + stacksize);
#endif
      }
#ifdef USE_TLS
# if TLS_DTV_AT_TP
    new_thread = (pthread_descr) ((char *) new_thread + TLS_PRE_TCB_SIZE);
# endif
    _dl_deallocate_tls (new_thread, true);
#endif
    __pthread_handles[sseg].h_descr = NULL;
    __pthread_handles[sseg].h_bottom = NULL;
    __pthread_handles_num--;
    return saved_errno;
  }
  /* Insert new thread in doubly linked list of active threads */
  new_thread->p_prevlive = __pthread_main_thread;
  new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
  __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
  __pthread_main_thread->p_nextlive = new_thread;
  /* Set pid field of the new thread, in case we get there before the
     child starts. */
  new_thread->p_pid = pid;
  return 0;
}
示例#8
0
static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
                                 void * (*start_routine)(void *), void *arg,
                                 sigset_t * mask, int father_pid)
{
  size_t sseg;
  int pid;
  pthread_descr new_thread;
  pthread_t new_thread_id;
  int i;

  /* Find a free stack segment for the current stack */
  for (sseg = 1; ; sseg++) {
    if (sseg >= PTHREAD_THREADS_MAX) return EAGAIN;
    if (__pthread_handles[sseg].h_descr != NULL) continue;
    new_thread = thread_segment(sseg);
    /* Allocate space for stack and thread descriptor. */
    if (mmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
             INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
             MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN, -1, 0)
        != (caddr_t) -1) break;
    /* It seems part of this segment is already mapped. Try the next. */
  }
  /* Allocate new thread identifier */
  pthread_threads_counter += PTHREAD_THREADS_MAX;
  new_thread_id = sseg + pthread_threads_counter;
  /* Initialize the thread descriptor */
  new_thread->p_nextwaiting = NULL;
  new_thread->p_tid = new_thread_id;
  new_thread->p_priority = 0;
  new_thread->p_spinlock = &(__pthread_handles[sseg].h_spinlock);
  new_thread->p_signal = 0;
  new_thread->p_signal_jmp = NULL;
  new_thread->p_cancel_jmp = NULL;
  new_thread->p_terminated = 0;
  new_thread->p_detached = attr == NULL ? 0 : attr->detachstate;
  new_thread->p_exited = 0;
  new_thread->p_retval = NULL;
  new_thread->p_joining = NULL;
  new_thread->p_cleanup = NULL;
  new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
  new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
  new_thread->p_canceled = 0;
  new_thread->p_errno = 0;
  new_thread->p_h_errno = 0;
  for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++)
    new_thread->p_specific[i] = NULL;
  /* Initialize the thread handle */
  __pthread_handles[sseg].h_spinlock = 0; /* should already be 0 */
  __pthread_handles[sseg].h_descr = new_thread;
  /* Determine scheduling parameters for the thread */
  new_thread->p_start_args.schedpolicy = SCHED_OTHER;
  if (attr != NULL && attr->schedpolicy != SCHED_OTHER) {
    switch(attr->inheritsched) {
    case PTHREAD_EXPLICIT_SCHED:
      new_thread->p_start_args.schedpolicy = attr->schedpolicy;
      new_thread->p_start_args.schedparam = attr->schedparam;
      break;
    case PTHREAD_INHERIT_SCHED:
      new_thread->p_start_args.schedpolicy = __sched_getscheduler(father_pid);
      __sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
      break;
    }
    new_thread->p_priority = 
      new_thread->p_start_args.schedparam.sched_priority;
  }
  /* Finish setting up arguments to pthread_start_thread */
  new_thread->p_start_args.start_routine = start_routine;
  new_thread->p_start_args.arg = arg;
  new_thread->p_start_args.mask = *mask;
  /* Do the cloning */
  pid = __clone(pthread_start_thread, (void **) new_thread,
                CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
                PTHREAD_SIG_RESTART,
                new_thread);
  /* Check if cloning succeeded */
  if (pid == -1) {
    /* Free the stack */
    munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
           INITIAL_STACK_SIZE);
    __pthread_handles[sseg].h_descr = NULL;
    return errno;
  }
  /* Insert new thread in doubly linked list of active threads */
  new_thread->p_prevlive = __pthread_main_thread;
  new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
  __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
  __pthread_main_thread->p_nextlive = new_thread;
  /* Set pid field of the new thread, in case we get there before the
     child starts. */
  new_thread->p_pid = pid;
  /* We're all set */
  *thread = new_thread_id;
  return 0;
}
/* Comments by Gene:
 * Here, syscall is the wrapper, and the call to syscall would be _real_syscall
 * We would add a special case for SYS_gettid, while all others default as below
 * It depends on the idea that arguments are stored in registers, whose
 *  natural size is:  sizeof(void*)
 * So, we pass six arguments to syscall, and it will ignore any extra arguments
 * I believe that all Linux system calls have no more than 7 args.
 * clone() is an example of one with 7 arguments.
 * If we discover system calls for which the 7 args strategy doesn't work,
 *  we can special case them.
 *
 * XXX: DO NOT USE JTRACE/JNOTE/JASSERT in this function; even better, do not
 *      use any STL here.  (--Kapil)
 */
extern "C" SYSCALL_ARG_RET_TYPE syscall(SYSCALL_ARG_RET_TYPE sys_num, ... )
{
  long int ret;
  va_list ap;

  va_start(ap, sys_num);

  switch ( sys_num ) {

    case SYS_clone:
    {
      typedef int (*fnc) (void*);
      SYSCALL_GET_ARGS_7(fnc, fn, void*, child_stack, int, flags, void*, arg,
                         pid_t*, pid, struct user_desc*, tls, pid_t*, ctid);
      ret = __clone(fn, child_stack, flags, arg, pid, tls, ctid);
      break;
    }

    case SYS_execve:
    {
      SYSCALL_GET_ARGS_3(const char*,filename,char* const *,argv,char* const *,envp);
      ret = execve(filename,argv,envp);
      break;
    }

    case SYS_fork:
    {
      ret = fork();
      break;
    }
    case SYS_exit:
    {
      SYSCALL_GET_ARG(int,status);
      exit(status);
      break;
    }
    case SYS_open:
    {
      SYSCALL_GET_ARGS_3(const char*,pathname,int,flags,mode_t,mode);
      ret = open(pathname, flags, mode);
      break;
    }
    case SYS_close:
    {
      SYSCALL_GET_ARG(int,fd);
      ret = close(fd);
      break;
    }

    case SYS_rt_sigaction:
    {
      SYSCALL_GET_ARGS_3(int,signum,const struct sigaction*,act,struct sigaction*,oldact);
      ret = sigaction(signum, act, oldact);
      break;
    }
    case SYS_rt_sigprocmask:
    {
      SYSCALL_GET_ARGS_3(int,how,const sigset_t*,set,sigset_t*,oldset);
      ret = sigprocmask(how, set, oldset);
      break;
    }
    case SYS_rt_sigtimedwait:
    {
      SYSCALL_GET_ARGS_3(const sigset_t*,set,siginfo_t*,info,
                        const struct timespec*, timeout);
      ret = sigtimedwait(set, info, timeout);
      break;
    }

#ifdef __i386__
    case SYS_sigaction:
    {
      SYSCALL_GET_ARGS_3(int,signum,const struct sigaction*,act,struct sigaction*,oldact);
      ret = sigaction(signum, act, oldact);
      break;
    }
    case SYS_signal:
    {
      typedef void (*sighandler_t)(int);
      SYSCALL_GET_ARGS_2(int,signum,sighandler_t,handler);
      // Cast needed:  signal returns sighandler_t
      ret = (long int)signal(signum, handler);
      break;
    }
    case SYS_sigprocmask:
    {
      SYSCALL_GET_ARGS_3(int,how,const sigset_t*,set,sigset_t*,oldset);
      ret = sigprocmask(how, set, oldset);
      break;
    }
#endif

#ifdef __x86_64__
// These SYS_xxx are only defined for 64-bit Linux
    case SYS_socket:
    {
      SYSCALL_GET_ARGS_3(int,domain,int,type,int,protocol);
      ret = socket(domain,type,protocol);
      break;
    }
    case SYS_connect:
    {
      SYSCALL_GET_ARGS_3(int,sockfd,const struct sockaddr*,addr,socklen_t,addrlen);
      ret = connect(sockfd, addr, addrlen);
      break;
    }
    case SYS_bind:
    {
      SYSCALL_GET_ARGS_3(int,sockfd,const struct sockaddr*,addr,socklen_t,addrlen);
      ret = bind(sockfd,addr,addrlen);
      break;
    }
    case SYS_listen:
    {
      SYSCALL_GET_ARGS_2(int,sockfd,int,backlog);
      ret = listen(sockfd,backlog);
      break;
    }
    case SYS_accept:
    {
      SYSCALL_GET_ARGS_3(int,sockfd,struct sockaddr*,addr,socklen_t*,addrlen);
      ret = accept(sockfd, addr, addrlen);
      break;
    }
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) && __GLIBC_PREREQ(2,10)
    case SYS_accept4:
    {
      SYSCALL_GET_ARGS_4(int,sockfd,struct sockaddr*,addr,socklen_t*,addrlen,int,flags);
      ret = accept4(sockfd, addr, addrlen, flags);
      break;
    }
#endif
    case SYS_setsockopt:
    {
      SYSCALL_GET_ARGS_5(int,s,int,level,int,optname,const void*,optval,socklen_t,optlen);
      ret = setsockopt(s, level, optname, optval, optlen);
      break;
    }

    case SYS_socketpair:
    {
      SYSCALL_GET_ARGS_4(int,d,int,type,int,protocol,int*,sv);
      ret = socketpair(d,type,protocol,sv);
      break;
    }
#endif

    case SYS_pipe:
    {
      SYSCALL_GET_ARG(int*,fds);
      ret = pipe(fds);
      break;
    }
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)) && __GLIBC_PREREQ(2,9)
    case SYS_pipe2:
    {
      SYSCALL_GET_ARGS_2(int*,fds,int,flags);
      ret = pipe2(fds, flags);
      break;
    }
#endif

    case SYS_setsid:
    {
      ret = setsid();
      break;
    }

#ifndef DISABLE_SYS_V_IPC
# ifdef __x86_64__
// These SYS_xxx are only defined for 64-bit Linux
    case SYS_shmget:
    {
      SYSCALL_GET_ARGS_3(key_t,key,size_t,size,int,shmflg);
      ret = shmget(key, size, shmflg);
      break;
    }
    case SYS_shmat:
    {
      SYSCALL_GET_ARGS_3(int,shmid,const void*,shmaddr,int,shmflg);
      ret = (unsigned long) shmat(shmid, shmaddr, shmflg);
      break;
    }
    case SYS_shmdt:
    {
      SYSCALL_GET_ARG(const void*,shmaddr);
      ret = shmdt(shmaddr);
      break;
    }
    case SYS_shmctl:
    {
      SYSCALL_GET_ARGS_3(int,shmid,int,cmd,struct shmid_ds*,buf);
      ret = shmctl(shmid, cmd, buf);
      break;
    }
# endif
#endif
    case SYS_poll:
    {
      SYSCALL_GET_ARGS_3(struct pollfd *,fds,nfds_t,nfds,int,timeout);
      ret = poll(fds, nfds, timeout);
      break;
    }
    case SYS_epoll_create:
    {
      SYSCALL_GET_ARG(int,size);
      ret = epoll_create(size);
      break;
    }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) && __GLIBC_PREREQ(2,4)
    case SYS_inotify_init:
    {
      ret = inotify_init();
      break;
    }
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) && __GLIBC_PREREQ(2,8)
    case SYS_signalfd:
    {
      SYSCALL_GET_ARGS_3(int,fd,sigset_t *,mask,int,flags);
      ret = signalfd(fd, mask, flags);
      break;
    }
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && __GLIBC_PREREQ(2,8)
    case SYS_signalfd4:
    {
      SYSCALL_GET_ARGS_3(int,fd,sigset_t *,mask,int,flags);
      ret = signalfd(fd, mask, flags);
      break;
    }
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) && __GLIBC_PREREQ(2,8)
    case SYS_eventfd:
    {
      SYSCALL_GET_ARGS_2(unsigned int,initval,int,flags);
      ret = eventfd(initval, flags);
      break;
    }
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && __GLIBC_PREREQ(2,8)
    case SYS_eventfd2:
    {
      SYSCALL_GET_ARGS_2(unsigned int,initval,int,flags);
      ret = eventfd(initval, flags);
      break;
    }
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && __GLIBC_PREREQ(2,9)
    case SYS_epoll_create1:
    {
      SYSCALL_GET_ARG(int,flags);
      ret = epoll_create(flags);
      break;
    }
    case SYS_inotify_init1:
    {
      SYSCALL_GET_ARG(int,flags);
      ret = inotify_init1(flags);
      break;
    }
#endif

    default:
    {
      SYSCALL_GET_ARGS_7(void*, arg1, void*, arg2, void*, arg3, void*, arg4,
                         void*, arg5, void*, arg6, void*, arg7);
      ret = _real_syscall(sys_num, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
      break;
    }
  }
  va_end(ap);
  return ret;
}
示例#10
0
int __pthread_initialize_manager(void)
{
  int manager_pipe[2];
  int pid;
  struct pthread_request request;

#ifndef HAVE_Z_NODELETE
  if (__builtin_expect (&__dso_handle != NULL, 1))
    __cxa_atexit ((void (*) (void *)) pthread_atexit_retcode, NULL,
		  __dso_handle);
#endif

  if (__pthread_max_stacksize == 0)
    __pthread_init_max_stacksize ();
  /* If basic initialization not done yet (e.g. we're called from a
     constructor run before our constructor), do it now */
  if (__pthread_initial_thread_bos == NULL) pthread_initialize();
  /* Setup stack for thread manager */
  __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
  if (__pthread_manager_thread_bos == NULL) return -1;
  __pthread_manager_thread_tos =
    __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;
  /* Setup pipe to communicate with thread manager */
  if (__libc_pipe(manager_pipe) == -1) {
    free(__pthread_manager_thread_bos);
    return -1;
  }
  /* Start the thread manager */
  pid = 0;
  if (__builtin_expect (__pthread_initial_thread.p_report_events, 0))
    {
      /* It's a bit more complicated.  We have to report the creation of
	 the manager thread.  */
      int idx = __td_eventword (TD_CREATE);
      uint32_t mask = __td_eventmask (TD_CREATE);

      if ((mask & (__pthread_threads_events.event_bits[idx]
		   | __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]))
	  != 0)
	{
	  __pthread_lock(__pthread_manager_thread.p_lock, NULL);

#ifdef NEED_SEPARATE_REGISTER_STACK
	  pid = __clone2(__pthread_manager_event,
			 (void **) __pthread_manager_thread_bos,
			 THREAD_MANAGER_STACK_SIZE,
			 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
			 (void *)(long)manager_pipe[0]);
#elif _STACK_GROWS_UP
	  pid = __clone(__pthread_manager_event,
			(void **) __pthread_manager_thread_bos,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
			(void *)(long)manager_pipe[0]);
#else
	  pid = __clone(__pthread_manager_event,
			(void **) __pthread_manager_thread_tos,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
			(void *)(long)manager_pipe[0]);
#endif

	  if (pid != -1)
	    {
	      /* Now fill in the information about the new thread in
	         the newly created thread's data structure.  We cannot let
	         the new thread do this since we don't know whether it was
	         already scheduled when we send the event.  */
	      __pthread_manager_thread.p_eventbuf.eventdata =
		&__pthread_manager_thread;
	      __pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE;
	      __pthread_last_event = &__pthread_manager_thread;
	      __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
	      __pthread_manager_thread.p_pid = pid;

	      /* Now call the function which signals the event.  */
	      __linuxthreads_create_event ();
	    }

	  /* Now restart the thread.  */
	  __pthread_unlock(__pthread_manager_thread.p_lock);
	}
    }

  if (__builtin_expect (pid, 0) == 0)
    {
#ifdef NEED_SEPARATE_REGISTER_STACK
      pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos,
		     THREAD_MANAGER_STACK_SIZE,
		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
		     (void *)(long)manager_pipe[0]);
#elif _STACK_GROWS_UP
      pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos,
		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
		    (void *)(long)manager_pipe[0]);
#else
      pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
		    (void *)(long)manager_pipe[0]);
#endif
    }
  if (__builtin_expect (pid, 0) == -1) {
    free(__pthread_manager_thread_bos);
    __libc_close(manager_pipe[0]);
    __libc_close(manager_pipe[1]);
    return -1;
  }
  __pthread_manager_request = manager_pipe[1]; /* writing end */
  __pthread_manager_reader = manager_pipe[0]; /* reading end */
  __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
  __pthread_manager_thread.p_pid = pid;
  /* Make gdb aware of new thread manager */
  if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0)
    {
      raise(__pthread_sig_debug);
      /* We suspend ourself and gdb will wake us up when it is
	 ready to handle us. */
      __pthread_wait_for_restart_signal(thread_self());
    }
  /* Synchronize debugging of the thread manager */
  request.req_kind = REQ_DEBUG;
  TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
				  (char *) &request, sizeof(request)));
  return 0;
}
示例#11
0
文件: os.c 项目: 8l/inferno
void
kproc(char *name, void (*func)(void*), void *arg, int flags)
{
	int pid;
	Proc *p;
	Pgrp *pg;
	Fgrp *fg;
	Egrp *eg;
	void *tos;

	p = newproc();
	if(0)
		print("start %s:%.8lx\n", name, p);
	if(p == nil) {
		print("kproc(%s): no memory", name);
		panic("kproc: no memory");
	}

	if(flags & KPDUPPG) {
		pg = up->env->pgrp;
		incref(&pg->r);
		p->env->pgrp = pg;
	}
	if(flags & KPDUPFDG) {
		fg = up->env->fgrp;
		incref(&fg->r);
		p->env->fgrp = fg;
	}
	if(flags & KPDUPENVG) {
		eg = up->env->egrp;
		incref(&eg->r);
		p->env->egrp = eg;
	}

	p->env->uid = up->env->uid;
	p->env->gid = up->env->gid;
	kstrdup(&p->env->user, up->env->user);

	strcpy(p->text, name);

	p->func = func;
	p->arg = arg;

	if(flags & KPX11){
		p->kstack = nil;	/* never freed; also up not defined */
		tos = (char*)mallocz(X11STACK, 0) + X11STACK - sizeof(void*);
	}else
		p->kstack = stackalloc(p, &tos);

	lock(&procs.l);
	if(procs.tail != nil) {
		p->prev = procs.tail;
		procs.tail->next = p;
	}
	else {
		procs.head = p;
		p->prev = nil;
	}
	procs.tail = p;
	unlock(&procs.l);

	if (__clone(tramp, tos, /*CLONE_PTRACE|*/CLONE_VM|CLONE_FS|CLONE_FILES|SIGCHLD, p) <= 0) {
		fprint(2, "emu: clone failed: %s\n", strerror(errno));
		panic("kproc: clone failed");
	}
}
示例#12
0
int main_client_thread(void)
{
    int clone_err = 0;
    int clone_var;
    int stack_index;
    int i,j,k,s;
    int rc;
    int exit_rc = 0;
    int s0;                   /* control socket */
    int wait_status;
    int clients_created = 0;
    struct sembuf mysembuf1;
    struct sembuf mysembuf2;
    unsigned char control_buffer;

    struct timezone tz1;
    struct timeval  tv1;
    struct timezone tz2;
    struct timeval  tv2;

    /*
     * create the control socket used to talk to the server.
     */

    exit_rc = create_client_socket (&s0);
    if (exit_rc)
        goto out_main;
    /*
     * tell the server how many rooms and messages.
     */
    start_message.nrooms = nrooms;
    start_message.nmessages = nmessages;
    rc = send (s0, &start_message, sizeof(start_message), 0);
    if (rc != sizeof(start_message)) {
        exit_rc = errno;
        perror ("CLI: send() start_message ");
        goto out_main;
    }

    /*
     * create threads via __clone that will connect to the server thread.
     * loop creates enough clients to satisfy the user specified
     * number of rooms.
     */

    for (i = 0 ; i < nrooms ; i++) {
        printf ("Creating room number %u ...\n", i+1);
        for (k = 0 ; k < CLIENTS_PER_ROOM ; k++) {
            clone_var   = i*CLIENTS_PER_ROOM+k;
            stack_index = (clone_var*STACK_SIZE)+STACK_SIZE;

            exit_rc = create_client_socket (&s);
            if (exit_rc)
                goto out_main;

            ti[clone_var].snd_socket = s;
            ti[clone_var].rcv_socket = s;

            clone_err = __clone(&cli_snd,
                                &c_send_stack[stack_index],
                                CLONE_FLAGS,
                                (void*)clone_var);

            if (clone_err == -1) {
                exit_rc = errno;
                perror ("CLI: clone() ");
                goto out_main;
            }

            clients_created++;
            clone_err = __clone(&cli_rcv,
                                &c_receive_stack[stack_index],
                                CLONE_FLAGS,
                                (void*)clone_var);

            if (clone_err == -1) {
                exit_rc = errno;
                perror ("CLI: clone() ");
                goto out_main;
            }

            clients_created++;
        }
        printf ("%u connections so far.\n", (i+1)*CLIENTS_PER_ROOM);
    }

    /* wait for the server to let us start. */

    if (cdebug) printf ("CLI: waiting for CLIENT_START msg from srv\n");

    exit_rc = wait_for_message(s0, CLIENT_START);
    if (exit_rc)
        goto out_main;

    if (cdebug) printf ("CLI: rcved CLIENT_START msg from srvr\n");

    /* clear the sema4 to allow client threads to start together. */

    mysembuf1.sem_num = 0;
    mysembuf1.sem_op  = clients_created;
    mysembuf1.sem_flg = 0;

    mysembuf2.sem_num = 0;
    mysembuf2.sem_op  = 0;
    mysembuf2.sem_flg = 0;

    printf ("Running the test ...\n");

    /* get start time */

    rc = gettimeofday (&tv1, &tz1);
    if (rc) {
        exit_rc = errno;
        perror ("gettimeofday failed on tv1 ");
        goto out_main;
    }

    /* start all of the clients */

    rc = semop (clientsemall, &mysembuf1, 1);
    if (rc == -1) {
        exit_rc = errno;
        perror ("CLI: semop(clientsemall) failed ");
        goto out_main;
    }

    /* wait until all of the clients complete */

    rc = semop (c_donesem, &mysembuf2, 1);
    if (rc == -1) {
        exit_rc = errno;
        perror ("CLI: semop(c_donesem) failed ");
        goto out_main;
    }

    /* get the end time */

    rc = gettimeofday (&tv2, &tz2);
    if (rc) {
        exit_rc = rc;
        perror ("gettimeofday failed on tv2 ");
        goto out_main;
    }

    printf ("Test complete.\n\n");

    timersub(&tv2, &tv1, &tvr); /* tvr now contains result of tv2-tv1 */

    for (i = 0 ; i < nrooms * CLIENTS_PER_ROOM ; i++) {
        rc = waitpid (-1, &wait_status, __WCLONE);
        if (rc == -1) {
            exit_rc = errno;
            perror ("SRV: wait() ");
        }
        rc = waitpid (-1, &wait_status, __WCLONE);
        if (rc == -1) {
            exit_rc = errno;
            perror ("SRV: wait() ");
        }
    }

    for (i = 0 ; i < nrooms * CLIENTS_PER_ROOM ; i++) {
        close(ti[i].snd_socket);
    }

    /*
     * send a control character to the main_server_thread to let him know
     * we are done;
     */

    control_buffer = CLIENT_END;

    rc = send (s0, &control_buffer, 1, 0);
    if (rc != 1) {
        exit_rc = errno;
        perror ("CLI: send() CLIENT_END control byte ");
        goto out_main;
    }

out_main:

    close(s0);
    return(exit_rc);
}