Exemple #1
0
void createmainthread()
{
	char print_queue[20]="main thread\n";
	void *stack;
	void *arg;
	node * mainthreadblock,*temptail;
	struct wrapper_arguments * wrapperarguments;
	stack = malloc( FIBER_STACK );
	write(1,print_queue,sizeof(print_queue));
	//total_threads+=1;
	if (stack == 0)
        {
                perror("malloc: could not allocate stack");
                exit(1);
        }
	arg=(void *) malloc(sizeof(void));
	mythread_t *mainthread=(mythread_t *) malloc (sizeof(mythread_t));
        mainthread->mystack = stack;
	mainthread->join_target=NULL;
        mainthread->myfunction =NULL;
        mainthread->myarguments=arg;
	mainthread->tid=0;
	futex_init(&(mainthread->thread_futex),0);

        mainthreadblock=createNode();
	temptail=(node *)malloc(sizeof(node));
        addNode(mainthreadblock);
	futex_init(&block_main_futex,0);
	ismainthreadcreated+=1;
	//futex_down(&block_main_futex);
}
/*
 * This function initializes the conditional variable referenced by cond
 * Pre:A reference to a uninitialized variable of type mythread_cond_t 
 * Post:An entry in the Conditional variable control block and is initialized
 * Returns: -1 on failure
 * 	     0 on success
 */
int mythread_cond_init(mythread_cond_t * cond,
		       const mythread_condattr_t * attr)
{
    // Preventing race conditions while updating ccb table and allocating memory
    mythread_enter_kernel();
    ccb_table =
	(ccb_t **) realloc(ccb_table,
			   sizeof(ccb_t *) * (nr_conditional_variables +
					      1));
    if (!ccb_table) {
	perror("Failed to extend conditional variable table\n");
	return -1;
    }
    ccb_table[nr_conditional_variables] = (ccb_t *) malloc(sizeof(ccb_t));
    if (!ccb_table[nr_conditional_variables]) {
	perror
	    ("Failed to allocate memory for the new conditional variable\n");
	return -1;
    }
    // Initialize thread control block resources
    *cond = (mythread_cond_t) nr_conditional_variables;
    futex_init(&ccb_table[nr_conditional_variables]->mutex, 1);
    //ccb_table[nr_conditional_variables]-> q = NULL;
    nr_conditional_variables++;
    mythread_leave_kernel();
    return 0;
}
Exemple #3
0
FairAllocator::FairAllocator( unsigned process_num , 
				Address memory_size): process_count(process_num),
									  memory_capacity( memory_size ), busy_pages(0)
{
	total_page_count = memory_size >> (zinfo->page_shift);
	//create descriptors for all pages
	for( Address i = 0; i < total_page_count; i++ )
	{
		 DRAMBufferBlock* block = new DRAMBufferBlock(i); 
		 buffer_array.push_back( block );	
		 global_clean_pool.push_back(i);
	}
	global_dirty_pool.clear();

	//for recording process taken space
	for( unsigned i=0 ; i<process_count; i++ )
	{
		g_unordered_set<Address> tmp;
		clean_pools.push_back(tmp);
		dirty_pools.push_back(tmp);
	}
	proc_busy_pages.resize(process_count);
	uint64_t max_pages=((uint64_t)2<<26);
	uint64_t min_pages = ((uint64_t)2<<17);
	//calculate min free pages
	min_free_pages = Min( Max((uint64_t)(4*sqrt(memory_size)),min_pages),max_pages);
	std::cout<<"min free pages:"<<std::hex<<min_free_pages<<std::endl;
	std::cout<<"min pages:"<<std::hex<<min_pages<<std::endl;
	std::cout<<"max pages:"<<std::hex<<max_pages<<std::endl;
	//min free page num
	min_free_pages /=(zinfo->page_size);
	futex_init(&pool_lock);
}
static int create_main_tcb(){

  mythread_t main_tcb = (mythread_t)malloc(sizeof(struct mythread));

  if(main_tcb == NULL){
    return -1;
  }

  /* Initialize main TCB */

  main_tcb -> tid = (pid_t) mythread_gettid();
  main_tcb -> start_func = NULL;
  main_tcb -> arg = NULL;
  main_tcb -> returnValue = NULL;
  main_tcb -> state = READY;
  

  /* Initialize futex for main thread */
  futex_init(&main_tcb->futex,0);
 
  /* Addition of this entry into the global queue is required */
  queue_add(main_tcb);
  
  return 0;  
}
/* When the first mythread_create call is invoked, we create the tcb corresponding
   to main and idle threads. The following function adds the tcb for main thread
   in front of the queue.
*/
static int __mythread_add_main_tcb()
{
	DEBUG_PRINTF("add_main_tcb: Creating node for Main thread \n");
	main_tcb = (mythread_private_t *) malloc(sizeof(mythread_private_t));
	if (main_tcb == NULL) {
		ERROR_PRINTF("add_main_tcb: Error allocating memory for main node\n");
		return -ENOMEM;
	}

	main_tcb->start_func = NULL;
	main_tcb->args = NULL;
	main_tcb->state = READY;
	main_tcb->returnValue = NULL;
	main_tcb->blockedForJoin = NULL;

	/* Get the main's tid and put it in its corresponding tcb. */
	main_tcb->tid = __mythread_gettid();

	/* Initialize futex to zero */
	futex_init(&main_tcb->sched_futex, 1);

	/* Put it in the Queue of thread blocks */
	mythread_q_add(main_tcb);
	return 0;
}
Exemple #6
0
void initialize_mythread_package()
{

	char print_queue[20]="queue initialized\n";
	void *stack;
	void *arg;
	int piddd;
	struct wrapper_arguments * wrapperarguments;

	stack = malloc( FIBER_STACK );
	if ( stack == 0 )
        {
                perror( "malloc: could not allocate stack" );
                exit( 1 );
         }

	arg=(void *) malloc(sizeof(void));

	mythread_t *idlethread=(mythread_t *) malloc (sizeof(mythread_t)); 
	init_queue_main();


	// create the main thread block and put it in the queue
	futex_init(&yield_futex,0);
	futex_init(&block_exitthread_futex,0);
	createmainthread();

	
	//create the idle thread
       	 futex_init(&f,0);
	 idlethread->mystack = stack;
         idlethread->myfunction =&idlethreadfunction;
         idlethread->myarguments=arg;
	 idlethread->join_target=NULL; 
	 wrapperarguments = (struct wrapper_arguments *) malloc (sizeof(struct wrapper_arguments));
         wrapperarguments->functionname=&idlethreadfunction;
         wrapperarguments->functionarguments=arg;
         wrapperarguments->tcb=idlethread;
	 futex_init(&(wrapperarguments->tcb->thread_futex),0);
        
	 void *wrapperarg = (void *) wrapperarguments;
	
 	 idlethread->tid = clone(&mythread_wrapper, (char*) stack + FIBER_STACK,
                SIGCHLD | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_VM,wrapperarg);

	futex_down(&f);
}
int mythread_create_idle(mythread_t *new_thread_ID,
        mythread_attr_t *attr,
        void * (*start_func)(void *),
        void *arg){

  int stacksize;
  void*child_stack = NULL;
  if(attr == NULL){
    stacksize = SIGSTKSZ;
    posix_memalign(&child_stack,8,stacksize);   /*Alignment of stack at 64 bit boundary*/
  } 
  else{
    stacksize = attr->stacksize;
    child_stack = attr->stackbase;
  }
  
  if(child_stack == NULL){
      return -1;
    }
  else{
    child_stack = child_stack + stacksize - sizeof(sigset_t);
  }
  
  
  /* Initialization of local TCB to be sent to the generic wrapper function */

  mythread_t new_tcb = (mythread_t)malloc(sizeof(struct mythread));
  if(new_tcb == NULL){
    return -1;
  }
  
  new_tcb -> start_func = start_func;
  new_tcb -> arg = arg;
  new_tcb -> state = READY;
  new_tcb -> joinq = NULL;
  new_tcb -> returnValue = NULL;

  /* Initialize futex for new thread to 0 not 1*/
  futex_init(&new_tcb->futex,0);
 
  /* Add this TCB to the global queue */
  queue_add(new_tcb);
  
  pid_t tid;
  if((tid = clone(mythread_wrapper,child_stack,(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND|CLONE_THREAD | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM),new_tcb))==-1){
    return -1;
  }

  /* Adding tid of thread to the TCB */
  new_tcb -> tid = tid;
  
  /* This is what the user will see as the TID */
  *new_thread_ID = new_tcb;

  //printf("The tid of thread as seen from the main is %ld \n",(long)new_thread_ID);
  
  return 0;        
}
Exemple #8
0
int mythread_create(mythread_t *new_thread_ID,
                    mythread_attr_t *attr,
                    void * (*start_func)(void *),
                    void *arg)
{
        mythread_t *mythread;
        struct wrapper_arguments *wrapperarguments;
        void* stack;
         pid_t pid;
         pid_t *childthreadid;
         int j=0;
         char ch;
	 char print_queue[20]="queue init\n";
         
	// Allocate the stack
         stack = malloc( FIBER_STACK );
	 mythread = (mythread_t *) malloc (sizeof(mythread_t));
	 mythread=new_thread_ID;
	 wrapperarguments = (struct wrapper_arguments *) malloc (sizeof(struct wrapper_arguments)); 	
	
	/* if mythread is called for the first time initialize the thread package */

	if (isfirsttime==0)
        {
		initialize_mythread_package();
	//isfirsttime2+=1;//new        
 	}
	else
	{
	//	futex_down(&f);
	}
	if ( stack == 0 )
         {
                 perror( "malloc: could not allocate stack" );
                exit( 1 );
         }
	 
 	 mythread->mystack = stack;
         mythread->myfunction =start_func;
         mythread->myarguments=arg;
         mythread->join_target=NULL;
	 mythread->myaddress=mythread;

	 wrapperarguments->functionname=start_func;
	 wrapperarguments->functionarguments=arg;
	 wrapperarguments->tcb=mythread;
	 futex_init(&(wrapperarguments->tcb->thread_futex),0);
	 void *wrapperarg = (void *) wrapperarguments;
        
        new_thread_ID-> tid = clone(&mythread_wrapper, (char*) stack + FIBER_STACK,
                CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_VM,wrapperarg);
       	
	futex_down(&block_main_futex);
	//write(1,"thread created dude\n",21);
        return 0;
}
Exemple #9
0
int collect_shmem(int pid, VmaEntry *vi)
{
	unsigned long size = vi->pgoff + vi->end - vi->start;
	struct shmem_info *si;

	si = find_shmem_by_id(vi->shmid);
	if (si) {

		if (si->size < size)
			si->size = size;
		si->count++;

		/*
		 * Only the shared mapping with a lowest
		 * pid will be created in real, other processes
		 * will wait until the kernel propagate this mapping
		 * into /proc
		 */
		if (!pid_rst_prio(pid, si->pid)) {
			if (si->pid == pid)
				si->self_count++;

			return 0;
		}

		si->pid	 = pid;
		si->start = vi->start;
		si->end	 = vi->end;
		si->self_count = 1;

		return 0;
	}

	si = rst_mem_alloc(sizeof(struct shmem_info), RM_SHREMAP);
	if (!si)
		return -1;

	pr_info("Add new shmem 0x%"PRIx64" (0x%016"PRIx64"-0x%016"PRIx64")\n",
				vi->shmid, vi->start, vi->end);

	si->start = vi->start;
	si->end	  = vi->end;
	si->shmid = vi->shmid;
	si->pid	  = pid;
	si->size  = size;
	si->fd    = -1;
	si->count = 1;
	si->self_count = 1;

	nr_shmems++;
	futex_init(&si->lock);

	return 0;
}
Exemple #10
0
int main(int argc, char** argv)
{
	if (futex_init(&f))
		return 1;
	if (futex_lock(&f))
		return 1;
	if (futex_unlock(&f))
		return 1;
	if (futex_destroy(&f))
		return 1;
	return 0;
}
Exemple #11
0
int mythread_mutex_init(mythread_mutex_t *mutex, const mythread_mutexattr_t *attr)
{

	mythread_mutex_t *mx =(mythread_mutex_t *)malloc(sizeof(mythread_mutex_t));
	mx=mutex;
	mx->lockvariable=0;
	mx->noofwaitingthreads=0;
	mx->noofblockedthreads=0;
	mx->isblockedthread=0;
	mx->blocked_threads=(mythread_queue_t * )malloc(sizeof(mythread_queue_t));
	mx->owner_thread=NULL;
	futex_init(&(mutex->blocking_futex),0);
	return 0; // 0  - SUCCESS
}
Exemple #12
0
void InitLog(const char* header, const char* file) {
    logHeader = strdup(header);
    futex_init(&log_printLock);

    if (file) {
        FILE* fd = fopen(file, "a");
        if (fd == nullptr) {
            perror("fopen() failed");
            panic("Could not open logfile %s", file); //we can panic in InitLog (will dump to stderr)
        }
        logFdOut = fd;
        logFdErr = fd;
        //NOTE: We technically never close this fd, but always flush it
    }
}
Exemple #13
0
MD1Memory::MD1Memory(uint32_t requestSize, uint32_t megacyclesPerSecond, uint32_t megabytesPerSecond, uint32_t _zeroLoadLatency, g_string& _name)
    : zeroLoadLatency(_zeroLoadLatency), name(_name)
{
    lastPhase = 0;

    double bytesPerCycle = ((double)megabytesPerSecond)/((double)megacyclesPerSecond);
    maxRequestsPerCycle = bytesPerCycle/requestSize;
    assert(maxRequestsPerCycle > 0.0);

    zeroLoadLatency = _zeroLoadLatency;

    smoothedPhaseAccesses = 0.0;
    curPhaseAccesses = 0;
    curLatency = zeroLoadLatency;

    futex_init(&updateLock);
}
Exemple #14
0
/* Heap segment size, in bytes. Can't grow for now, so choose something sensible, and within the machine's limits (see sysctl vars kernel.shmmax and kernel.shmall) */
int gm_init(size_t segmentSize) {
    /* Create a SysV IPC shared memory segment, attach to it, and mark the segment to
     * auto-destroy when the number of attached processes becomes 0.
     *
     * IMPORTANT: There is a small window of vulnerability between shmget and shmctl that
     * can lead to major issues: between these calls, we have a segment of persistent
     * memory that will survive the program if it dies (e.g. someone just happens to send us
     * a SIGKILL)
     */

    assert(GM == NULL);
    assert(gm_shmid == 0);
    gm_shmid = shmget(IPC_PRIVATE, segmentSize, 0644 | IPC_CREAT /*| SHM_HUGETLB*/);
    if (gm_shmid == -1) {
        perror("gm_create failed shmget");
        exit(1);
    }
    GM = static_cast<gm_segment*>(shmat(gm_shmid, GM_BASE_ADDR, 0));
    if (GM != GM_BASE_ADDR) {
        perror("gm_create failed shmat");
        warn("shmat failed, shmid %d. Trying not to leave garbage behind before dying...", gm_shmid);
        int ret = shmctl(gm_shmid, IPC_RMID, NULL);
        if (ret) {
            perror("shmctl failed, we're leaving garbage behind!");
            panic("Check /proc/sysvipc/shm and manually delete segment with shmid %d", gm_shmid);
        } else {
            panic("shmctl succeeded, we're dying in peace");
        }
    }

    //Mark the segment to auto-destroy when the number of attached processes becomes 0.
    int ret = shmctl(gm_shmid, IPC_RMID, NULL);
    assert(!ret);

    char* alloc_start = reinterpret_cast<char*>(GM) + 1024;
    size_t alloc_size = segmentSize - 1 - 1024;
    GM->base_regp = NULL;

    GM->mspace_ptr = create_mspace_with_base(alloc_start, alloc_size, 1 /*locked*/);
    futex_init(&GM->lock);
    assert(GM->mspace_ptr);

    return gm_shmid;
}
int main(int argc, char **argv)
{	
	int i;
	char buffer[1024];
	futex_init(&printFutex, 1);
	mythread_t mythread1[NTHREADS];
	mythread_t signalingThread[NTHREADS/2];
	mythread_setconcurrency(4);
	mythread_mutex_init(&mutex,NULL);
	mythread_cond_init(&condition,NULL);
	mythread_barrier_init(&barrier,NULL,NTHREADS+1);
	
	/* Create Threads */
	for(i=0;i<NTHREADS;i++){
		sprintf(buffer, "Created thread : %d\n", i+1);
		printToConsole(buffer);
		mythread_create(&mythread1[i],NULL,&thread_func, NULL);
	}
	
	/*Signal threads waiting on cond var*/
	while(count<NTHREADS){
		/* Special case for testing broadcast*/
		if(count == NTHREADS/2){
			mythread_cond_broadcast(&condition);
		}else{
			mythread_cond_signal(&condition);
		}
	}
	
	/* Waiting on barrier. Last thread, or this main thread will unblock the barrier depending on the execution sequence */
	mythread_barrier_wait(&barrier);
	sprintf(buffer, "Out of barrier, main thread exiting..\n");
	printToConsole(buffer);
	/* Destroy mutex, barrier and cond*/
	mythread_cond_destroy(&condition);
        mythread_mutex_destroy(&mutex);
	mythread_barrier_destroy(&barrier);
	sprintf(buffer, "Finished Execution\n");
	printToConsole(buffer);
}
Exemple #16
0
NormalPaging::NormalPaging(PagingStyle select): mode(select),cur_page_table_num(0)
 {
		debug_printf("create legacy paging");
		assert(zinfo);
		if( select == Legacy_Normal)
		{
			zinfo->page_size = 4*power(2,10);	//4KB
			zinfo->page_shift = 12;	
		}
		else if(select == Legacy_Huge)
		{	
			zinfo->page_size = 4*power(2,20);
			zinfo->page_shift=22;
		}
		PageTable* table= gm_memalign<PageTable>( CACHE_LINE_BYTES, 1);
		page_directory = new(table)PageTable(ENTRY_1024);
		debug_printf("zinfo->block size is: %d",zinfo->block_size);
		buffer_table_entry_num = zinfo->page_size/zinfo->block_size;
		buffer_table_shift = zinfo->page_shift - zinfo->block_shift;
		debug_printf("create legacy paging succeed");
		futex_init(&table_lock);
 }
Exemple #17
0
int futex(int *uaddr, int op, int val,
          const struct timespec *timeout,
          int *uaddr2, int val3)
{
  uint64_t ms_timeout = (uint64_t)-1;
  assert(uaddr2 == NULL);
  assert(val3 == 0);
  if(timeout != NULL) {
    ms_timeout = timeout->tv_sec*1000 + timeout->tv_nsec/1000000L;
    assert(ms_timeout > 0);
  }

  run_once(futex_init());
  switch(op) {
    case FUTEX_WAIT:
      return futex_wait(uaddr, val, ms_timeout);
    case FUTEX_WAKE:
      return futex_wake(uaddr, val);
    default:
      errno = ENOSYS;
      return -1;
  }
  return -1;
}
Exemple #18
0
LongModePaging::LongModePaging(PagingStyle select): mode(select),cur_pdp_num(0),cur_pd_num(0),cur_pt_num(0)
{
  PageTable* table = gm_memalign<PageTable>(CACHE_LINE_BYTES,1);
  pml4=new (table) PageTable(512);
  assert(zinfo);
  if(select == LongMode_Normal)			//4KB
  {
	zinfo->page_size = 4*power(2,10);
	zinfo->page_shift = 12;
  }
  else if(select == LongMode_Middle )			//2MB
  {
	zinfo->page_size = 4*power(2,10);
	zinfo->page_shift=21;
  }
  else if(select == LongMode_Huge )			//1GB
  {
	zinfo->page_size=power(2,30);	
	zinfo->page_shift = 30;
  }
  buffer_table_entry_num = zinfo->page_size/zinfo->block_size;
  buffer_table_shift = zinfo->page_shift - zinfo->block_shift;
  futex_init(&table_lock);
}
Exemple #19
0
 inline FutexLock()
 {
     futex_init(&m_lock);
 }
Exemple #20
0
void
os_init(char *argv[], char *envp[])
{
    /* Conduct various version checks: do we have enough mmap(), is
     * this a sparc running 2.2, can we do threads? */
    struct utsname name;
    int major_version;
    int minor_version;
    int patch_version;
    char *p;
    uname(&name);
    p=name.release;
    major_version = atoi(p);
    p=strchr(p,'.')+1;
    minor_version = atoi(p);
    p=strchr(p,'.')+1;
    patch_version = atoi(p);
    if (major_version<2) {
        lose("linux kernel version too old: major version=%d (can't run in version < 2.0.0)\n",
             major_version);
    }
    if (!(major_version>2 || minor_version >= 4)) {
#ifdef LISP_FEATURE_SPARC
        FSHOW((stderr,"linux kernel %d.%d predates 2.4;\n enabling workarounds for SPARC kernel bugs in signal handling.\n", major_version,minor_version));
        linux_sparc_siginfo_bug = 1;
#endif
    }
#ifdef LISP_FEATURE_SB_THREAD
#if !defined(LISP_FEATURE_SB_LUTEX) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX)
    futex_init();
#endif
    if(! isnptl()) {
       lose("This version of SBCL only works correctly with the NPTL threading\n"
            "library. Please use a newer glibc, use an older SBCL, or stop using\n"
            "LD_ASSUME_KERNEL\n");
    }
#endif

    /* Don't use getpagesize(), since it's not constant across Linux
     * kernel versions on some architectures (for example PPC). FIXME:
     * possibly the same should be done on other architectures too.
     */
    os_vm_page_size = BACKEND_PAGE_BYTES;

    /* KLUDGE: Disable memory randomization on new Linux kernels
     * by setting a personality flag and re-executing. (We need
     * to re-execute, since the memory maps that can conflict with
     * the SBCL spaces have already been done at this point).
     *
     * Since randomization is currently implemented only on x86 kernels,
     * don't do this trick on other platforms.
     */
#if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
    if ((major_version == 2
         /* Some old kernels will apparently lose unsupported personality flags
          * on exec() */
         && ((minor_version == 6 && patch_version >= 11)
             || (minor_version > 6)
             /* This is what RHEL 3 reports */
             || (minor_version == 4 && patch_version > 20)))
        || major_version >= 3)
    {
        int pers = personality(0xffffffffUL);
        /* 0x40000 aka. ADDR_NO_RANDOMIZE */
        if (!(pers & 0x40000)) {
            int retval = personality(pers | 0x40000);
            /* Allegedly some Linux kernels (the reported case was
             * "hardened Linux 2.6.7") won't set the new personality,
             * but nor will they return -1 for an error. So as a
             * workaround query the new personality...
             */
            int newpers = personality(0xffffffffUL);
            /* ... and don't re-execute if either the setting resulted
             * in an error or if the value didn't change. Otherwise
             * this might result in an infinite loop.
             */
            if (retval != -1 && newpers != pers) {
                /* Use /proc/self/exe instead of trying to figure out
                 * the executable path from PATH and argv[0], since
                 * that's unreliable. We follow the symlink instead of
                 * executing the file directly in order to prevent top
                 * from displaying the name of the process as "exe". */
                char runtime[PATH_MAX+1];
                int i = readlink("/proc/self/exe", runtime, PATH_MAX);
                if (i != -1) {
                    runtime[i] = '\0';
                    execve(runtime, argv, envp);
                }
            }
            /* Either changing the personality or execve() failed. Either
             * way we might as well continue, and hope that the random
             * memory maps are ok this time around.
             */
            fprintf(stderr, "WARNING: Couldn't re-execute SBCL with the proper personality flags (maybe /proc isn't mounted?). Trying to continue anyway.\n");
        }
    }
#ifdef LISP_FEATURE_X86
    /* Use SSE detector.  Recent versions of Linux enable SSE support
     * on SSE capable CPUs.  */
    /* FIXME: Are there any old versions that does not support SSE?  */
    fast_bzero_pointer = fast_bzero_detect;
#endif
#endif
}
/* mythread_create function creates a new thread using clone system call.
   It passes wrapper function to the clone system which invokes the user function.
   attr can also be passed, if not passed, then default attr will be used. 
 */
int mythread_create(mythread_t* new_thread,
		    mythread_attr_t * attr,
		    void *(*start_func) (void *), void *arg)
{
	/* Global thread queue would be empty on first mythread_create call. 
	   This would add the main thread in the queue and also an idle thread, 
 	   and then proceed with the new thread creation */

	if (mythread_queue_globalVar == NULL) {
		mythread_queue_globalVar = malloc(sizeof(struct mythread_queue));
		mythread_t *main_t_tcb = (mythread_t *) malloc(sizeof(mythread_t));

		/* Initializing TCB values for main thread */

		main_t_tcb->start_func = NULL; /* There is no explicit function to call for the main thread */
		main_t_tcb->state = READY;
		main_t_tcb->returnValue = NULL;
		main_t_tcb->arg = NULL;
		main_t_tcb->joinq.headNode = NULL;
		main_t_tcb->joinq.tailNode = NULL;
		main_t_tcb->tid = (pid_t) syscall(SYS_gettid);

		/* Initialize main thread futex */
		futex_init(&main_t_tcb->futex, 0);

		/* Adding main thread to the queue */
		queue_add_element(mythread_queue_globalVar, main_t_tcb);

		/* Initialise the yeild futex */
		futex_init(&yield_futex, 1);

		/* Recursive call to mythread_create for the idle thread creation*/
		mythread_create(&idle_tcb, NULL, idle_thread, NULL);
	}

	mythread_t *new_mythread_t = (mythread_t *) malloc(sizeof(mythread_t));
	pid_t tid;

	/* Clone flags to be passed, taken from pthread source code - CLONE_PTRACE is removed */
	int clone_flags = (CLONE_VM | CLONE_FS  
			   | CLONE_FILES | CLONE_SIGHAND 
			   | CLONE_PARENT_SETTID | CLONE_THREAD
			   | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM);

	/* Check if attr is passed, if not, initialize with default attr */
	if (attr == NULL || (attr->stackbase == NULL && attr->stacksize != 0)){
		mythread_attr_t attr_new;
		mythread_attr_init(&attr_new);
		attr = &attr_new;
	}

	/* Initialize new thread's TCB */
	new_mythread_t->arg = arg;
	new_mythread_t->state = READY;
	new_mythread_t->start_func = start_func;
	new_mythread_t->joinq.headNode = NULL;
	new_mythread_t->joinq.tailNode = NULL;
	new_mythread_t->returnValue = NULL;

	/* Initialize the tcb's futex to zero. */
	futex_init(&new_mythread_t->futex, 0);

	/* Clone system call. This will invoke the wrapper_function. */
	tid = clone(wrapper_function, (char *)attr->stackbase, clone_flags,new_mythread_t);

	new_mythread_t->tid = tid;
	/* Returning the reference of the created TCB */
	*new_thread = *new_mythread_t;

	/* Adding the thread to the global TCB queue */
	queue_add_element(mythread_queue_globalVar, new_mythread_t);
	return 0;
}
int mythread_create(mythread_t *new_thread_ID,
		    mythread_attr_t *attr,
		    void * (*start_func)(void *),
		    void *arg){

  

  /* Call the create_main_tbc() funciton */
  
  if(head_ptr==NULL){
    if(create_main_tcb() != 0){
      return -1;
    }

    /* Futex to let the idle thread always runs along with another thread */
    futex_init(&global_futex,1);
    /*
    if((mythread_create_idle(&idle_thread,NULL,idle_activity,NULL)==-1)){
      return -1;
    } 
    */
  }

  
  /* Allocate Memory for Stack */
  
  int stacksize;
  void* child_stack = NULL;
  if(attr == NULL){
    stacksize = SIGSTKSZ;
    posix_memalign(&child_stack,8,stacksize);   /*Alignment of stack at 64 bit boundary*/
  } 
  else{
    stacksize = attr->stacksize;
    if(attr->stackbase==NULL){
      posix_memalign(&child_stack,8,stacksize);
    }
    else{
      child_stack = attr->stackbase;
    }
    
  }
  
  if(child_stack == NULL){
      return -1;
    }
  else{
    child_stack = child_stack + stacksize - sizeof(sigset_t);
  }
  
  
  /* Initialization of local TCB to be sent to the generic wrapper function */

  mythread_t new_tcb = (mythread_t)malloc(sizeof(struct mythread));
  if(new_tcb == NULL){
    return -1;
  }
  
  new_tcb -> start_func = start_func;
  new_tcb -> arg = arg;
  new_tcb -> state = READY;
  new_tcb -> returnValue = NULL;

  /* Initialize futex for new thread to 0 not 1*/
  futex_init(&new_tcb->futex,0);
 
  /* Add this TCB to the global queue */
  queue_add(new_tcb);
  
  pid_t tid;
  if((tid = clone(mythread_wrapper,(char*)child_stack,(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND|CLONE_THREAD | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM),new_tcb))==-1){
    return -1;
  }
  
  /* Adding tid of thread to the TCB */
  new_tcb -> tid = tid;
  
  /* This is what the user will see as the TID */
  *new_thread_ID = new_tcb;

  //printf("The tid of thread as seen from the main is %ld \n",(long)new_thread_ID);
  
  return 0;    
}
Exemple #23
0
int main(int argc, char *argv[])
{
	struct futex *futex;
	int fd;
	void *map;

	if (argc != 4) {
		fprintf(stderr, "Usage: test <file> <offset> show|init|up|upfair|down|down1sec|mem|async\n");
		exit(1);
	}
	fd = open(argv[1], O_RDWR);
	if (fd < 0) {
		perror("opening file");
		exit(1);
	}
	map = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
	if (map == MAP_FAILED) {
		perror("mmap");
		exit(1);
	}

	if (futex_region(map, 4096) != 0) {
		perror("futex_region");
		exit(1);
	}
	futex = map + atoi(argv[2]);
	if (strcmp(argv[3], "init") == 0)
		futex_init(futex);
	else if (strcmp(argv[3], "up") == 0) {
		int woken;
		woken = futex_up(futex);
		if (woken < 0) {
			perror("futex_up");
			exit(1);
		}
		printf("Woke %i\n", woken);
	} else if (strcmp(argv[3], "upfair") == 0) {
		int woken;
		woken = futex_up_fair(futex);
		if (woken < 0) {
			perror("futex_up");
			exit(1);
		}
		printf("Woke %i\n", woken);
	} else if (strcmp(argv[3], "down") == 0) {
		if (futex_down(futex) != 0) {
			perror("futex_down");
			exit(1);
		}
	} else if (strcmp(argv[3], "down1sec") == 0) {
		struct timespec t;
		t.tv_sec = 1;
		t.tv_nsec = 0;
		if (futex_down_timeout(futex, &t) != 0) {
			perror("futex_down_timeout");
			exit(1);
		}
	} else if (strcmp(argv[3], "mem") == 0) {
		struct futex myfutex;
		futex_init(&myfutex);
		futex_down(&myfutex);
		futex_down(&myfutex);
	} else if (strcmp(argv[3], "show") == 0) {
		printf("count = %i\n", futex->count);
	} else if (strcmp(argv[3], "async") == 0) {
		static struct sigaction saction;
		int futex_fd;

		/* Set up SIGIO handler */
		saction.sa_sigaction = sigio_action;
		saction.sa_flags = SA_SIGINFO|SA_ONESHOT;

		while (futex_trydown(futex) != 0) {
			/* Register for signal */
			sigaction(SIGIO, &saction, NULL);
			futex_fd = futex_await(futex, SIGIO);
			if (futex_fd < 0) {
				perror("await");
				exit(1);
			}
			if (futex_trydown(futex) == 0) {
				close(futex_fd);
				break;
			}
			pause();
			close(futex_fd);
			/* <= in case someone else decremented it */
			if (futex->count <= FUTEX_PASSED) {
				futex->count = -1;
				fprintf(stderr, "Futex was passed to us.\n");
				break;
			}
		}
	} else {
		fprintf(stderr, "Unknown operation %s\n", argv[3]);
		exit(1);
	}
		
	exit(0);
}
/* The mythread_create() function.
   This creates a shared process context by using the clone system call.
   We pass the pointer to a wrapper function ( See mythread_wrapper.c ) which in turn 
   sets up the thread environment and then calls the thread function.
   The mythread_attr_t argument can optionally specify the stack size to be used
   the newly created thread.
 */
int mythread_create(mythread_t * new_thread_ID,
		    mythread_attr_t * attr,
		    void *(*start_func) (void *), void *arg)
{

	/* pointer to the stack used by the child process to be created by clone later */
	char *child_stack;

	unsigned long stackSize;
	mythread_private_t *new_node;
	pid_t tid;
	int retval;

	/* Flags to be passed to clone system call. 
	   This flags variable is picked up from pthread source code - with CLONE_PTRACE removed. 
	 */
	int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL
			   | CLONE_PARENT_SETTID
			   | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM);

	if (mythread_q_head == NULL) {
		/* This is the very first mythread_create call. Set up the Q first with tcb nodes for main thread. */
		retval = __mythread_add_main_tcb();
		if (retval != 0)
			return retval;

		/* Initialise the global futex */
		futex_init(&gfutex, 1);

		/* Now create the node for Idle thread with a recursive call to mythread_create(). */
		DEBUG_PRINTF("create: creating node for Idle thread \n");
		mythread_create(&idle_u_tcb, NULL, mythread_idle, NULL);
	}

	/* This particular piece of code was added as a result of a weird bug encountered in the __futex_down().
	 * In 2.6.35 (our kernel version), all threads can access main thread's stack, but
	 * on the OS machine, this stack is somehow private to main thread only. 
	 */
	new_node = (mythread_private_t *) malloc(sizeof(mythread_private_t));
	if (new_node == NULL) {
		ERROR_PRINTF("Cannot allocate memory for node\n");
		return -ENOMEM;
	}

	/* If Stack-size argument is not provided, use the SIGSTKSZ as the default stack size 
	 * Otherwise, extract the stacksize argument.
	 */
	if (attr == NULL)
		stackSize = SIGSTKSZ;
	else
		stackSize = attr->stackSize;

	/* posix_memalign aligns the allocated memory at a 64-bit boundry. */
	if (posix_memalign((void **)&child_stack, 8, stackSize)) {
		ERROR_PRINTF("posix_memalign failed! \n");
		return -ENOMEM;
	}

	/* We leave space for one invocation at the base of the stack */
	child_stack = child_stack + stackSize - sizeof(sigset_t);

	/* Save the thread_fun pointer and the pointer to arguments in the TCB. */
	new_node->start_func = start_func;
	new_node->args = arg;
	/* Set the state as READY - READY in Q, waiting to be scheduled. */
	new_node->state = READY;

	new_node->returnValue = NULL;
	new_node->blockedForJoin = NULL;
	/* Initialize the tcb's sched_futex to zero. */
	futex_init(&new_node->sched_futex, 0);

	/* Put it in the Q of thread blocks */
	mythread_q_add(new_node);

	/* Call clone with pointer to wrapper function. TCB will be passed as arg to wrapper function. */
	if ((tid =
	     clone(mythread_wrapper, (char *)child_stack, clone_flags,
		   new_node)) == -1) {
		printf("clone failed! \n");
		printf("ERROR: %s \n", strerror(errno));
		return (-errno);
	}
	/* Save the tid returned by clone system call in the tcb. */
	new_thread_ID->tid = tid;
	new_node->tid = tid;

	DEBUG_PRINTF("create: Finished initialising new thread: %ld\n",
		     (unsigned long)new_thread_ID->tid);
	return 0;
}