Exemple #1
0
/*
  The gtthread_init() function does not have a corresponding pthread equivalent.
  It must be called from the main thread before any other GTThreads
  functions are called. It allows the caller to specify the scheduling
  period (quantum in micro second), and may also perform any other
  necessary initialization.  If period is zero, then thread switching should
  occur only on calls to gtthread_yield().

  Recall that the initial thread of the program (i.e. the one running
  main() ) is a thread like any other. It should have a
  gtthread_t that clients can retrieve by calling gtthread_self()
  from the initial thread, and they should be able to specify it as an
  argument to other GTThreads functions. The only difference in the
  initial thread is how it behaves when it executes a return
  instruction. You can find details on this difference in the man page
  for pthread_create.
 */
void gtthread_init(long period){
  gtthread_int_t *mainthread;

  /* Malloc for this thread */
  if ((mainthread = malloc(sizeof(gtthread_int_t))) != NULL){

    /* Initialize queues */
    steque_init(&threads);
    steque_init(&run_queue);

    /* Set up mainthread */
    mainthread->id = next_id++;
    mainthread->cancelreq = 0;
    mainthread->completed = 0;
    steque_init(&mainthread->join_queue);

    /* Set up the context */
    getcontext(&mainthread->context);
    mainthread->context.uc_stack.ss_sp = (char *) malloc(SIGSTKSZ);
    mainthread->context.uc_stack.ss_size = SIGSTKSZ;

    steque_enqueue(&threads, mainthread);
    steque_enqueue(&run_queue, mainthread);

    /* Initialize the scheduling quantum */
    quantum = period;

    if (quantum != 0) {
      /* Setting up the signal mask */
      sigemptyset(&vtalrm);
      sigaddset(&vtalrm, SIGVTALRM);

      /* Setting up the alarm */
      timer = (struct itimerval*) malloc(sizeof(struct itimerval));
      timer->it_value.tv_sec = timer->it_interval.tv_sec = 0;
      timer->it_value.tv_usec = timer->it_interval.tv_usec = quantum;

      /* Setting up the handler */
      memset(&act, '\0', sizeof(act));
      act.sa_handler = &alrm_handler;
      if (sigaction(SIGVTALRM, &act, NULL) < 0) {
        printf("sigaction");
      }

      setitimer(ITIMER_VIRTUAL, timer, NULL);
      sigprocmask(SIG_UNBLOCK, &vtalrm, NULL);
    }
  }
  // FIXME: what about the error case?
}
Exemple #2
0
int gtcache_init(size_t capacity, size_t min_entry_size, int num_levels){
  int i;

  /* Initialize cache metadata */
  cache.max_entries = capacity / min_entry_size;
  cache.num_entries = 0;
  cache.mem_used = 0;
  cache.capacity = capacity;
  cache.min_entry_size = min_entry_size;

  /* Initialize cache */
  cache.entries = malloc(cache.max_entries * sizeof(cache_entry_t));
  for (i = 0; i < cache.max_entries; i++) {
    cache.entries[i].data = NULL;
    cache.entries[i].url = NULL;
    cache.entries[i].size = 0;
  }

  /* Initialize other data structures */
  /* Hash table should be at least twice the size of expected number of entries */
  hshtbl_init(&url_to_id_tbl, cache.max_entries * 2);
  indexminpq_init(&id_by_time_pq, cache.max_entries, keycmp);
  steque_init(&free_ids);

  /* Populate free_ids */
  for (i = cache.max_entries - 1; i >= 0; i--) {
    steque_push(&free_ids, i);
  }

  return 1;
}
/*
  The gtthread_init() function does not have a corresponding pthread equivalent.
  It must be called from the main thread before any other GTThreads
  functions are called. It allows the caller to specify the scheduling
  period (quantum in micro second), and may also perform any other
  necessary initialization.  If period is zero, then thread switching should
  occur only on calls to gtthread_yield().

  Recall that the initial thread of the program (i.e. the one running
  main() ) is a thread like any other. It should have a
  gtthread_t that clients can retrieve by calling gtthread_self()
  from the initial thread, and they should be able to specify it as an
  argument to other GTThreads functions. The only difference in the
  initial thread is how it behaves when it executes a return
  instruction. You can find details on this difference in the man page
  for pthread_create.
 */
void gtthread_init(long period){
  gtthread_t main_id = tid++;

  q = (steque_t*)malloc(sizeof(steque_t));
  steque_init(q);

  void* main_item;
  main_item = (node_t*)malloc(sizeof(node_t));
  ((node_t*)main_item) -> thread_ctx =  (ucontext_t*)malloc(sizeof(ucontext_t));
  ((node_t*)main_item) -> id = main_id;
  getcontext(((node_t*)main_item) -> thread_ctx);
  //TODO: need to init context?

  steque_enqueue(q, main_item);

  /*
    Setting up the signal mask
  */
  sigemptyset(&vtalrm);
  sigaddset(&vtalrm, SIGVTALRM);
  sigprocmask(SIG_UNBLOCK, &vtalrm, NULL);

  T = (struct itimerval*) malloc(sizeof(struct itimerval));
  p = period;

  set_alarm();
}
void init_proxy() {
		
		 steque_init(&fldes_queue);
		
		// create segment

		
		for (int i = 0; i < segments; i++) {
			
			char str_id[16] = "";

			sprintf(str_id, "%d", i);
			segment_id = (char*) malloc((strlen(str_id) + strlen(SHAREDMPATH) + 1) * sizeof(char));
			bzero(segment_id, (strlen(str_id) + strlen(SHAREDMPATH) + 1) * sizeof(char));
			strcpy(segment_id, SHAREDMPATH);
			strcat(segment_id, str_id);

			shm_unlink(segment_id);
			fprintf(stdout, "Created Segment ID: %s\n", segment_id);
			fflush(stdout);
			steque_enqueue(&fldes_queue, segment_id);
		}
	
		fldes_queue_size = steque_size(&fldes_queue);
        max_fldes_queue_size = steque_size(&fldes_queue);
//		fprintf(stdout, "init queue done.\n");

}
Exemple #5
0
int  gtthread_create(gtthread_t *thread, void *(*start_routine)(void *), void *arg)
{
  if (init != 1)
  {
 	/*printf("Error - gtthread not initialized. \n");*/
	exit(-1);
  }
  else
  {
	gtthread *newThread, *current;
	sigset_t oldset;

	/* Block alarms */
	sigprocmask(SIG_BLOCK, &alrm, &oldset);
	/* sigprocmask(SIG_BLOCK, &alrm, NULL); */

	/* do malloc for new thread and init its attributes */
	if((newThread = malloc(sizeof(gtthread))) != NULL)
	{
		newThread -> id = thread_num++;
		newThread -> finished = 0;
		newThread -> cancel = 0;
		/* store thread id */
		*thread = newThread -> id;
		
		/* get thread at front of currently running queue*/
		current = (gtthread *) gtthread_self();

		/* getcontext() */
		if ( getcontext(&newThread -> uctx) == 0)
		{
			newThread -> uctx.uc_stack.ss_sp = (char*) malloc(SIGSTKSZ);
			newThread -> uctx.uc_stack.ss_size = SIGSTKSZ;	
			/* set its successor context */
			newThread -> uctx.uc_link = &current -> uctx;
		}
	
		/* init join queue for the new thread */
		steque_init(&newThread -> joining);
		
		makecontext(&newThread -> uctx, (void (*)(void)) run_thread, 2, start_routine, arg);


		/* Add new thread to back of queue */
		steque_enqueue(&globalQ, newThread);
		steque_enqueue(&currently_running, newThread);
	
		sigprocmask(SIG_UNBLOCK, &alrm, NULL);
  	}	
  	else
  	{
		/*printf("Thread creation malloc failed. Exiting.\n");*/
		sigprocmask(SIG_UNBLOCK, &alrm, NULL);
		return 1;/* ? */
  	}

  	return 0;
  }
}
/* Main - entry point */
int main(int argc, char **argv) {
  steque_t queue;
  pthread_t producer_thread, consumer_thread;
  void *thread_return = NULL;
  int result = 0;

  /* Initialization */

  printf("Main thread started with thread id %"PRIdPTR"\n", (intptr_t) pthread_self());

  steque_init(&queue);

  g_num_prod = 1; /* there will be 1 producer thread */

  /* Create producer and consumer threads */

  result = pthread_create(&producer_thread, NULL, producer_routine, &queue);
  if (0 != result) {
    fprintf(stderr, "Failed to create producer thread: %s\n", strerror(result));
    exit(1);
  }

  printf("Producer thread started with thread id %" PRIdPTR "\n", (intptr_t) producer_thread);

  result = pthread_detach(producer_thread);
  if (0 != result)
    fprintf(stderr, "Failed to detach producer thread: %s\n", strerror(result));

  result = pthread_create(&consumer_thread, NULL, consumer_routine, &queue);
  if (0 != result) {
    fprintf(stderr, "Failed to create consumer thread: %s\n", strerror(result));
    exit(1);
  }

  /* Join threads, handle return values where appropriate */

  result = pthread_join(consumer_thread, &thread_return);
  if (0 != result) {
    fprintf(stderr, "Failed to join consumer thread: %s\n", strerror(result));
    pthread_exit(NULL);
  }
  //BUG: Don't join and detach a thread
  /*result = pthread_join(producer_thread, NULL);
  if (0 != result) {
    fprintf(stderr, "Failed to join producer thread: %s\n", strerror(result));
    pthread_exit(NULL);
  }*/

  printf("\nPrinted %"PRIdPTR" characters.\n", (intptr_t) thread_return);
  //BUG: Thread return isn't a pointer
  //free(thread_return);

  pthread_mutex_destroy(&g_queue_lock);
  pthread_mutex_destroy(&g_num_prod_lock);
  return 0;
}
Exemple #7
0
/*
  The gtthread_init() function does not have a corresponding pthread equivalent.
  It must be called from the main thread before any other GTThreads
  functions are called. It allows the caller to specify the scheduling
  period (quantum in micro second), and may also perform any other
  necessary initialization.

  Recall that the initial thread of the program (i.e. the one running
  main() ) is a thread like any other. It should have a
  gtthread_t that clients can retrieve by calling gtthread_self()
  from the initial thread, and they should be able to specify it as an
  argument to other GTThreads functions. The only difference in the
  initial thread is how it behaves when it executes a return
  instruction. You can find details on this difference in the man page
  for pthread_create.
 */
void gtthread_init(long period)
{
    struct sigaction act;

    /* initializing data structures */
    maxtid = 1;
    steque_init(&ready_queue);
    
    /* create main thread and add it to ready queue */  
    /* only main thread is defined on heap and can be freed */
    thread_t* main_thread = (thread_t*) malloc(sizeof(thread_t));
    main_thread->tid = maxtid++;
    main_thread->ucp = (ucontext_t*) malloc(sizeof(ucontext_t)); 
    memset(main_thread->ucp, '\0', sizeof(ucontext_t));
    main_thread->arg = NULL;
    main_thread->state = GTTHREAD_RUNNING;
    main_thread->joining = 0;

    /* must be called before makecontext */
    if (getcontext(main_thread->ucp) == -1)
    {
      perror("getcontext");
      exit(EXIT_FAILURE);
    }

    current = main_thread;
    
    /* setting uo the signal mask */
    sigemptyset(&vtalrm);
    sigaddset(&vtalrm, SIGVTALRM);
    sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); /* in case this is blocked previously */

    /* set alarm signal and signal handler */
    timer.it_interval.tv_usec = period;
    timer.it_interval.tv_sec = 0;
    timer.it_value.tv_usec = period;
    timer.it_value.tv_sec = 0; 
    
    if (setitimer(ITIMER_VIRTUAL, &timer, NULL) < 0)
    {
        perror("setitimer");
        exit(EXIT_FAILURE);
    }

    /* install signal handler for SIGVTALRM */  
    memset(&act, '\0', sizeof(act));
    act.sa_handler = &sigvtalrm_handler;
    if (sigaction(SIGVTALRM, &act, NULL) < 0)
    {
      perror ("sigaction");
      exit(EXIT_FAILURE);
    }
}
Exemple #8
0
/*
The gtthread_init() function does not have a corresponding pthread equivalent.
It must be called from the main thread before any other GTThreads
functions are called. It allows the caller to specify the scheduling
period (quantum in micro second), and may also perform any other
necessary initialization.  If period is zero, then thread switching should
occur only on calls to gtthread_yield().

Recall that the initial thread of the program (i.e. the one running
main() ) is a thread like any other. It should have a
gtthread_t that clients can retrieve by calling gtthread_self()
from the initial thread, and they should be able to specify it as an
argument to other GTThreads functions. The only difference in the
initial thread is how it behaves when it executes a return
instruction. You can find details on this difference in the man page
for pthread_create.
*/
void gtthread_init(long period){
  steque_init(&g_threads_steque);
  steque_init(&g_dead_threads_steque);
  steque_init(&g_cancelatorium);
  steque_init(&g_join_steque);
  
  global_period = period;
  
  // Setting up the signal mask
  if(set_up_alarm()) {
    perror("Error setting up alarm");
    exit(EXIT_FAILURE);
  }
  
  gtthread_t *main_thread = malloc(sizeof(gtthread_t));
  
  // Sets the thread id and other attributes.
  main_thread->id = g_thread_id++;
  main_thread->is_finished = 0;
  main_thread->is_joined = -1;
  main_thread->wait_tid = -1L;
  main_thread->retval = NULL;
  
  main_thread->context = (ucontext_t *) malloc(sizeof(ucontext_t));
  
  if(getcontext(main_thread->context) == -1) {
    perror("Error calling getcontext()");
    exit(EXIT_FAILURE);
  }
  
  // Creating a stack for the context.
  main_thread->context->uc_stack.ss_sp = (char *) malloc(SIGSTKSZ);
  main_thread->context->uc_stack.ss_size = SIGSTKSZ;
  
  steque_enqueue(&g_threads_steque, main_thread);
}
/*
  The gtthread_init() function does not have a corresponding pthread equivalent.
  It must be called from the main thread before any other GTThreads
  functions are called. It allows the caller to specify the scheduling
  period (quantum in micro second), and may also perform any other
  necessary initialization.  If period is zero, then thread switching should
  occur only on calls to gtthread_yield().

  Recall that the initial thread of the program (i.e. the one running
  main() ) is a thread like any other. It should have a
  gtthread_t that clients can retrieve by calling gtthread_self()
  from the initial thread, and they should be able to specify it as an
  argument to other GTThreads functions. The only difference in the
  initial thread is how it behaves when it executes a return
  instruction. You can find details on this difference in the man page
  for pthread_create.
 */
void gtthread_init(long period){

  ucontext_t uctx_main;
  gtthread_blk_t *main_thread;

  /* Initialize the thread queue */
  steque_init(&thread_queue);
    
  //fprintf(stderr, "gtthread_init\n"); 
  DEBUG_MSG("gtthread_init\n");

  /* Create main thread and put into queue */

  /************************* Initialize the context *************************************/

  if(getcontext(&uctx_main) == -1){ 
    printf("getcontext FAIL!\n");
    return;
  }

  uctx_main.uc_stack.ss_sp = (char*) malloc(SIGSTKSZ);
  uctx_main.uc_stack.ss_size = SIGSTKSZ;
  uctx_main.uc_link = NULL;

  //makecontext(&uctx_main, thread_handler, 0);      // modify the context 

  /************************** Initialize the thread block *************************************/

  if(!(main_thread = malloc(sizeof(gtthread_blk_t)))){
    printf("main_thread created failed\n");
    return;
  }
  main_thread->tID = thread_ID++;
  main_thread->state = RUNNING;
  main_thread->uctx = uctx_main;

  /********************************************************************************************/

  steque_enqueue(&thread_queue, main_thread);                     // add the thread to the scheduler queue

  sigprocmask(SIG_UNBLOCK, &vtalrm, NULL);                        // enable alarm signal


  /* Initialize timer and alarm */
  timer_init(period);


}
Exemple #10
0
static void load_requests(char *workload_path){
  FILE *file_handle;
  request_t *req;

  file_handle = fopen(workload_path, "r");
  if (file_handle == NULL) {
    fprintf(stderr,"cannot open workload file %s", workload_path);
    exit(EXIT_FAILURE);
  }

  steque_init(&queue);
  req = (request_t*) malloc(sizeof(request_t));
  while (fscanf(file_handle, "%s %s", req->inputfilename, req->outputfilename) != EOF){
    steque_enqueue(&queue, req);
    req = (request_t*) malloc(sizeof(request_t));
  }
  free(req);

  fclose(file_handle);
}
Exemple #11
0
void InitializeThreadConstructs()
{
    printf("Initializing thread constructs...\n");

    _queue = malloc(sizeof(steque_t));
    steque_init(_queue);
    printf("Queue initialized\n");

    if (pthread_mutex_init(&_queueLock, NULL) != 0)
    {
        printf("\n Queue lock mutex init failed\n");
        exit(1);
    }

    if (pthread_mutex_init(&_fileLock, NULL) != 0)
    {
        printf("\n File lock mutex init failed\n");
        exit(1);
    }
}
Exemple #12
0
void handler_init(int _num_threads){
    char name[BUFFER_SIZE];
    pthread_attr_t attributes;
    pthread_attr_init(&attributes);
    thread_info_t* thread_info = calloc(_num_threads, sizeof(thread_info_t));
    
        
    for (int i = 0; i < _num_threads; i++) {
        memset(name, 0, BUFFER_SIZE);
        snprintf(name, BUFFER_SIZE,"thread_%d",i);
        thread_info[i].name = strdup(name);
        thread_info[i].thread_num = i;
    
        int success = pthread_create(&thread_info[i].thread_id, &attributes, (void*)&thread_main, &thread_info[i]);
        if (success != 0) error("pthread_create failed");
    
    }
    
    steque_init(&request_queue);
    pthread_attr_destroy(&attributes);

}
Exemple #13
0
/*
  The gtthread_create() function mirrors the pthread_create() function,
  only default attributes are always assumed.
 */
int gtthread_create(gtthread_t *thread,
		    void *(*start_routine)(void *),
		    void *arg){
  gtthread_int_t *thread_int, *self;
  sigset_t oldset;

  sigprocmask(SIG_BLOCK, &vtalrm, &oldset);

  /* Malloc for this new thread */
  if ((thread_int = malloc(sizeof(gtthread_int_t))) != NULL){
    /* Initialize thread values */
    /* Block alarms */
    thread_int->id = next_id++;
    *thread = thread_int->id;
    thread_int->cancelreq = 0;
    thread_int->completed = 0;
    steque_init(&thread_int->join_queue);

    /* Set up the context */
    getcontext(&thread_int->context);
    thread_int->context.uc_stack.ss_sp = (char *) malloc(SIGSTKSZ);
    thread_int->context.uc_stack.ss_size = SIGSTKSZ;
    self = (gtthread_int_t *) steque_front(&run_queue);
    thread_int->context.uc_link = &self->context;
    makecontext(&thread_int->context, (void (*)(void)) start_wrapper, 2, start_routine, arg);

    /* Add new thread to data structures */
    steque_enqueue(&threads, thread_int);
    steque_enqueue(&run_queue, thread_int);
    /* Unblock alarms */
  }

  sigprocmask(SIG_UNBLOCK, &vtalrm, NULL);
  //FIXME: error case?
  
  /* Return 0 on success */
  return 0;
}
Exemple #14
0
/* main */
int main(int argc, char **argv) {
    int option_char = 0;
    unsigned short port = 8888;
    unsigned short nworkerthreads = 1;
    char *server = "s3.amazonaws.com/content.udacity-data.com";
    size_t shm_segsize = 4 * KBYTE;
    fprintf(stderr, "server = %s\n", server);

    if (signal(SIGINT, _sig_handler) == SIG_ERR){
        fprintf(stderr,"Can't catch SIGINT...exiting.\n");
        exit(EXIT_FAILURE);
    }

    if (signal(SIGTERM, _sig_handler) == SIG_ERR){
        fprintf(stderr,"Can't catch SIGTERM...exiting.\n");
        exit(EXIT_FAILURE);
    }

    /* Parse and set command line arguments */
    while ((option_char = getopt_long(argc, argv, "p:t:s:z:n:h", gLongOptions, NULL)) != -1) {
        switch (option_char) {
            case 'p': // listen-port
              port = atoi(optarg);
                break;
            case 't': // thread-count
                nworkerthreads = atoi(optarg);
                break;
            case 's': // file-path
                server = optarg;
                break;
            case 'z': // shm segment size
                shm_segsize = atoi(optarg);
                break;
            case 'n': // shm segment count 
                shm_segcount = atoi(optarg);
                break;                                                                          
            case 'h': // help
                fprintf(stdout, "%s", USAGE);
                exit(0);
                break;       
            default:
                fprintf(stderr, "%s", USAGE);
                exit(1);
        }
    }
  
    /* Initialize steque to hold shm segment ids */
    steque_init(&shm_segnum_queue);

    /* SHM initialization...*/
    /* Initially spawn 100 threads */    
    long shm_segnum;
    int shm_fd;
    char shm_segid[SEGID_LEN];

    /* total size of shared memory segment is size of the struct + requested segment size */    
    size_t shm_blocksize = sizeof(Shm_Block) + shm_segsize;
    printf("shm_blocksize = %zu\n", shm_blocksize);

    for (shm_segnum = 0; shm_segnum < shm_segcount; shm_segnum++) {
        sprintf(shm_segid, "/%ld", shm_segnum);

        /* Steps to create SHM segment id */  

        /* Delete previous shm instance of same name */
        if (shm_unlink(shm_segid) == -1) {
            //warn("main", "No previous shared memory instance found");
        }

        /* Create file descritor */
        shm_fd = shm_open(shm_segid, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
        if (shm_fd == -1) {
            err_exit("webproxy", "shm_open", errno);
        }

        /* adjust the memory region to size of shmbuf */
        if (ftruncate(shm_fd, shm_blocksize) == -1) {
            err_exit("main", "ftruncate", errno);
        }
        
        /* map the memory */
        Shm_Block *shmb_p;
        shmb_p = mmap(NULL, shm_blocksize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
        if (shmb_p == MAP_FAILED) {
            err_exit("main", "mmap failed", errno);
        }

        /* Push the segnum into the queue; because steque performs 
        only a shallow copy, we need to push elemental types, not 
        pointers. */
        steque_push(&shm_segnum_queue, (steque_item)shm_segnum);

        /* close the SHM file descriptors, they're no longer needed */   
        close(shm_fd);
    }

    /* Set up message queue attrs */
    struct mq_attr attr;
    attr.mq_maxmsg = MQ_MAXMSG;
    attr.mq_msgsize = MQ_MSGSIZE;

    /* Open message mqueue with specified attributes */
    mqd = mq_open(mq_name, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR, &attr);
    if (mqd == (mqd_t) -1){
        strerr_exit("webproxy, mq_open", errno);
    }
    
    /* Initialize mutex and cv to protect segqueue*/
    pthread_mutex_init(&sq_mtx, NULL);
    pthread_cond_init(&sq_notempty, NULL);

    /* Initializing server */
    gfserver_init(&gfs, nworkerthreads);

    /* Setting options */
    gfserver_setopt(&gfs, GFS_PORT, port);
    gfserver_setopt(&gfs, GFS_MAXNPENDING, 10);
    gfserver_setopt(&gfs, GFS_WORKER_FUNC, handle_with_cache);

    /* Spawn threads */
    num_writers = 0;
    num_readers = nworkerthreads;

    long *th_ids = (long *) malloc(nworkerthreads * sizeof(long)); 
    int i;
    for(i = 0; i < nworkerthreads; i++) {
        th_ids[i] = i;
        // fprintf(stderr, "Assigning thread id %ld\n", th_ids[i]);

        /* Construct workload context to pass on to the handler */
        Workload wld;
        wld.shm_blocksize = shm_blocksize;
        wld.mqd = mqd;                      /* populate mq file desc */
        wld.segqueue = &shm_segnum_queue;   /* populate segment queue id */
        wld.sq_mtx_p = &sq_mtx;             /* populate the mutex */
        wld.sq_notempty_p = &sq_notempty; /* populate cv */

        gfserver_setopt(&gfs, GFS_WORKER_ARG, i, &wld);
    }

    free(th_ids);
    /* Loops forever */
    gfserver_serve(&gfs);

}
Exemple #15
0
void gtthread_init(long period)
{
	if((mthread = malloc(sizeof(gtthread))) != NULL) /* if malloc successful */
	{
		/* init thread */
		mthread -> id = thread_num++;
		mthread -> finished = 0;
		mthread -> cancel = 0;

		/* getcontext() */
		if(getcontext(&mthread -> uctx) == 0)
		{
			mthread -> uctx.uc_stack.ss_sp = (char*) malloc(SIGSTKSZ);
			mthread -> uctx.uc_stack.ss_size = SIGSTKSZ;
			mthread -> uctx.uc_link = NULL;
		}

		/* init queues */
		steque_init(&globalQ);
		steque_init(&currently_running);
		steque_init(&mthread -> joining);
		
		/* add main thread to global queue and currently running queue*/
		steque_enqueue(&globalQ, mthread);
		steque_enqueue(&currently_running, mthread);

		/* now setting timer and alarm */
		/* preemption only allowed if period valid & != 0) */
		if(period != 0 && period > 0) 
		{
			sigemptyset(&alrm);
			sigaddset(&alrm, SIGVTALRM); 
			sigprocmask(SIG_UNBLOCK, &alrm, NULL);

			T = (struct itimerval*) malloc(sizeof(struct itimerval));
			T -> it_value.tv_sec = T -> it_interval.tv_sec = 0;
			T -> it_value.tv_usec = T -> it_interval.tv_usec = period;

			/* alarm handler */
			memset(&preempt, '\0', sizeof(preempt));
			preempt.sa_handler = &alrm_handler;
			if (sigaction(SIGVTALRM, &preempt, NULL) < 0) 
			{
				perror ("sigaction");
				exit(1);
  			}

			setitimer(ITIMER_VIRTUAL, T, NULL);
		}
		else /*if period != 0, there is nothing else to be done!*/
		{
			/*printf("Period initialized to 0. Preemption turned off. \n");*/
		}
		
	} 
	else
	{
		/*printf("gtthread_init malloc failed. Exiting.\n") ;*/
		exit(-1);

	}

	init = 1;
}
Exemple #16
0
/* Main ========================================================= */
int main(int argc, char **argv) {
  int i, option_char = 0;
  unsigned short port = 8888;
  unsigned short nworkerthreads = 1;
  unsigned short nsegments = 1;
  unsigned long segment_size = 1024;
  char *server = "s3.amazonaws.com/content.udacity-data.com";
  struct shm_info *shm_blk;

  if (signal(SIGINT, _sig_handler) == SIG_ERR){
    fprintf(stderr,"Can't catch SIGINT...exiting.\n");
    exit(EXIT_FAILURE);
  }

  if (signal(SIGTERM, _sig_handler) == SIG_ERR){
    fprintf(stderr,"Can't catch SIGTERM...exiting.\n");
    exit(EXIT_FAILURE);
  }

  // Parse and set command line arguments
  while ((option_char = getopt_long(argc, argv, "n:z:p:t:s:h", gLongOptions,
   NULL)) != -1) {
    switch (option_char) {
      case 'n': // num segments
        nsegments = atoi(optarg);
        break;
      case 'z': // size of segments
        segment_size = atol(optarg);
        break;
      case 'p': // listen-port
        port = atoi(optarg);
        break;
      case 't': // thread-count
        nworkerthreads = atoi(optarg);
        break;
      case 's': // file-path
        server = optarg;
        break;                                          
      case 'h': // help
        fprintf(stdout, "%s", USAGE);
        exit(0);
        break;       
      default:
        fprintf(stderr, "%s", USAGE);
        exit(1);
    }
  }
  
  /* SHM initialization...*/

  /*Initializing server*/
  gfserver_init(&gfs, nworkerthreads);

  /*Setting options*/
  gfserver_setopt(&gfs, GFS_PORT, port);
  gfserver_setopt(&gfs, GFS_MAXNPENDING, 10);
  gfserver_setopt(&gfs, GFS_WORKER_FUNC, handle_with_cache);

  steque_init(&segfds_q);
  /* Create the segments */
  for (i = 0; i < nsegments; i++) {
    shm_blk = malloc(sizeof(*shm_blk));
    snprintf(shm_blk->mem_name, sizeof(shm_blk->mem_name), "mem_%d", i);
    if (shm_unlink(shm_blk->mem_name) == 0) {
      fprintf(stdout, "Shared mem %s removed from system.\n",
        shm_blk->mem_name);
    }
    shm_blk->memfd = shm_open(shm_blk->mem_name, O_CREAT | O_RDWR | O_TRUNC,
        0777);
    if (shm_blk->memfd < 0) {
      perror("shm_open");
      exit(1);
    }
    ftruncate(shm_blk->memfd, segment_size);
    snprintf(shm_blk->sem1_name, sizeof(shm_blk->sem1_name), "sem_%d_1", i);
    if (sem_unlink(shm_blk->sem1_name) == 0) {
      fprintf(stdout, "Semaphore %s removed from system.\n",
        shm_blk->sem1_name);
    }
    snprintf(shm_blk->sem2_name, sizeof(shm_blk->sem2_name), "sem_%d_2", i);
    if (sem_unlink(shm_blk->sem2_name) == 0) {
      fprintf(stdout, "Semaphore %s removed from system.\n",
        shm_blk->sem2_name);
    }
    steque_push(&segfds_q, shm_blk);
  }
  for(i = 0; i < nworkerthreads; i++)
    gfserver_setopt(&gfs, GFS_WORKER_ARG, i, server);

  handle_with_cache_init(&segfds_q, segment_size, &segfds_q_mutex,
      &segfds_q_cond);

  /*Loops forever*/
  gfserver_serve(&gfs);
}