Exemplo n.º 1
0
int main(void){

  List *empty_list = list_new_empty_list();
  fprintf(stdout, "Test Case 0\n-------------------\n");
  list_print(empty_list);
  list_destroy(empty_list);

  fprintf(stdout, "\nTest Case 1\n-------------------\n");
  List *list_a = list_new_empty_list();
  for (int i=1; i<=10; i++){
    int *value = (int *)malloc(sizeof(int)); 
    *value = i;
    list_insert_data_after_element(list_a, (void *)value, list_a->tail);
  }

  list_print(list_a);

  fprintf(stdout, "\nTest Case 2\n-------------------\n");
  for (int i=11; i<=20; i++){
    int *value = (int *)malloc(sizeof(int)); 
    *value = i;
    if (i % 2 == 0){
      list_insert_data_after_element(list_a, value, NULL);
    }else{
      list_insert_data_after_element(list_a, (void *)value, list_a->tail);
    }
  }
  list_print(list_a);

  fprintf(stdout, "\nTest Case 3\n-------------------\n");
  for (int i=0; i<3; i++){
    void *data = NULL;
    list_remove_element(list_a, list_a->head, &data);
    fprintf(stdout, "removed an element[%3d]\n", *(int *)data);
    free(data);
  }
  list_print(list_a);

  fprintf(stdout, "\nTest Case 4\n-------------------\n");
  for (int i=0; i<3; i++){
    void *data = NULL;
    list_remove_element(list_a, list_a->tail, &data);
    fprintf(stdout, "removed an element[%3d]\n", *(int *)data);
    free(data);
  }
  list_print(list_a);

  list_destroy(list_a);
  fprintf(stdout, "Test Case 5\n-------------------\n");
  list_print(list_a);


  return 0;
}
Exemplo n.º 2
0
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.
		osp_spin_lock (&d->mutex);
		if (filp->f_flags & F_OSPRD_LOCKED)
		{	
			
			d->check_deadlock_list_head = list_remove_element(d->check_deadlock_list_head, current->pid);
			if (check_list_not_empty(d))
		{
			eprintk("not empty");
			//clean_list(d);
			
		}
			//delete_check_deadlock_list(current->pid,d);
			if (filp_writable)
			{
				d->number_write_lock --;
				d->write_lock_holder = -1;
			}

			else
			{
				d->number_read_lock--;
				d->pid_list_head = list_remove_element(d->pid_list_head,current->pid);
				//if (d->pid_list_head == NULL)
				//	return -ENOTTY;
			}
		}
		filp->f_flags = filp->f_flags & ~F_OSPRD_LOCKED;
		//delete_check_deadlock_list(current->pid,d);
		/*if (check_list_not_empty(d))
		{
			eprintk("not empty");
			clean_list(d);
			
		}*/
		osp_spin_unlock (&d->mutex);
		wake_up_all (&(d->blockq));

			}

	return 0;
}
Exemplo n.º 3
0
/*Used by sendFromInboxWithThrottle*/
static void
sendFromInboxMsgAction (void* closure1, void *closure2)
{
    mama_status status = MAMA_STATUS_OK;

    struct publisherClosure *c2 = (struct publisherClosure*)closure2;

    mamaPublisherImpl *impl = (mamaPublisherImpl*)c2->mPublisher;

    status = mamaPublisher_sendFromInbox ((mamaPublisher)impl,
                                          c2->mInbox,
                                          (mamaMsg)closure1);

    if (c2->mSendCompleteCallback)
    {
        c2->mSendCompleteCallback (
                (mamaPublisher)impl,
                (mamaMsg)closure1,
                status,
                c2->mSendCompleteClosure);
    }

    list_remove_element (impl->mPendingActions, c2);
    list_free_element (impl->mPendingActions, c2);
}
Exemplo n.º 4
0
static void
removeMessagesFromListCb (wList list, void *element, void *throttle) 
{
    wombatThrottleAction *action = (wombatThrottleAction*)element;
    list_remove_element (self->mMsgQueue, *action);
    list_free_element (self->mMsgQueue, *action);
    gRemoveCount++;
}
Exemplo n.º 5
0
mama_status
wombatThrottle_removeAction (wombatThrottle throttle, 
                             wombatThrottleAction action)
{
    list_remove_element (self->mMsgQueue, action);
    list_free_element (self->mMsgQueue, action);
    return MAMA_STATUS_OK;
}
/**
 * We pass this function to commands so they can tell the CmResponder to
 * remove them from the pending list and clean up when the command completes.
 */
static void 
endCB (mamaCommand *command, void *closure)
{
    mamaCmResponderImpl* impl = (mamaCmResponderImpl*) closure;
    list_remove_element (impl->mPendingCommands, command);
    command->mDtor (command->mHandle);
    list_free_element (impl->mPendingCommands, command);
}
Exemplo n.º 7
0
void *list_remove(link_list *list, void *data, list_comp comp)
{
	list_element *le;
	if(!list || !data || !comp) return NULL;
	for(le = list->first; le; le = le->next)
		if(comp(le->data, data))
			return list_remove_element(list, le);
	return NULL;
}
Exemplo n.º 8
0
/* ---------------------- small helper fucntions ---------------------------------- */
struct my_list* list_free( struct my_list* s )
{
	while(s->head)
	{
		list_remove_element(s);
	}

	return s;
}
Exemplo n.º 9
0
void *list_pop_back(link_list *list)
{
	assert(list);
	if(!list->last)
	{
		assert(!list->first);
		return NULL;
	}
	
	return list_remove_element(list, list->last);
}
Exemplo n.º 10
0
int main()
{
  list_head head;
   head = create_list();
   
   printf("Original list  : ");
   print_list(head);

   list_remove_element(&head, 0);
   printf("After remove 0 : ");
   print_list(head);
   
   list_remove_element(&head, 5);
   printf("After remove 5 : ");
   print_list(head);

   list_remove_element(&head, 9);
   printf("After remove 9 : ");
   print_list(head);
   return 0;

}
Exemplo n.º 11
0
static void
removeMessagesForOwnerCb (wList list, void *element, void *closure)
{
    MsgProperties *info = (MsgProperties*)element;
    biclosure* pair = (biclosure*)closure;

    if (pair->owner == info->mOwner)
    {
        list_remove_element (pair->impl->mMsgQueue, element);

        list_free_element (pair->impl->mMsgQueue, element);
        gRemoveCount++;
    }
}
Exemplo n.º 12
0
mama_status
mamaStatsGenerator_removeStatsCollector (mamaStatsGenerator statsGenerator, mamaStatsCollector statsCollector)
{
    mamaStatsGeneratorImpl* impl = (mamaStatsGeneratorImpl*)statsGenerator;
     mamaStatsCollectorImpl* collectorImpl = (mamaStatsCollectorImpl*)statsCollector;

    if (impl==NULL) return MAMA_STATUS_NULL_ARG;
    if (statsCollector==NULL) return MAMA_STATUS_NULL_ARG;

    list_remove_element (impl->mStatsCollectors, collectorImpl->mHandle);
    list_free_element (impl->mStatsCollectors, collectorImpl->mHandle);

    return MAMA_STATUS_OK;
}
Exemplo n.º 13
0
/*list destory*/
void list_destroy(devList *list){
	sky_trace_enter();
	void *data;
	devNode *element;
	int size = 0;
	while( ( size = list_size(list) ) > 0 ){
		sleep(1);
		element = list_tail(list);
		if(list_remove_element(list,element,(void **)&data) == 0 
				&& list->destroy != NULL ){
			list->destroy(data);
		}
		
	}
	memset(list,0x00,sizeof(devList));
	sky_trace_exit();
	return ;
}
Exemplo n.º 14
0
mama_status
mamaTimeZone_destroy (mamaTimeZone  timeZone)
{
    if (!timeZone)
    {
        return MAMA_STATUS_INVALID_ARG;
    }
    else
    {
        /* Remove from the list and free the memory. */
        mamaTimeZoneImpl* impl = (mamaTimeZoneImpl*)timeZone;
        wList tzList;
        wthread_static_mutex_lock (&sVector_mutex);
        tzList = getTimeZones();
        list_remove_element (tzList, impl);
        list_free_element (tzList, impl);
        wthread_static_mutex_unlock (&sVector_mutex);
        return MAMA_STATUS_OK;
    }
}
Exemplo n.º 15
0
/*Action function used with sendWithThrottle*/
static void
sendMsgAction (void *closure1, void *closure2)
{
    mama_status status = MAMA_STATUS_OK;
    struct publisherClosure* pc = (struct publisherClosure*)closure2;

    mamaPublisherImpl* impl = (mamaPublisherImpl*)pc->mPublisher;

    status = mamaPublisher_send ((mamaPublisher)impl, (mamaMsg)closure1);

    if (pc->mSendCompleteCallback)
    {
        pc->mSendCompleteCallback (pc->mPublisher,
                                   (mamaMsg)closure1,
                                   status,
                                   pc->mSendCompleteClosure);
    }

    list_remove_element (impl->mPendingActions, pc);
    list_free_element (impl->mPendingActions, pc);
}
Exemplo n.º 16
0
int main(void)
{
	struct my_list*  mt = NULL;

	mt = list_new();
	list_add_element(mt, 1,1);
	list_add_element(mt, 2,2);
	list_add_element(mt, 3,3);
	list_add_element(mt, 4,4); 

	list_print(mt);

	list_remove_element(mt);
	list_print(mt);

	list_free(mt);   /* always remember to free() the malloc()ed memory */
	free(mt);        /* free() if list is kept separate from free()ing the structure, I think its a good design */
	mt = NULL;      /* after free() always set that pointer to NULL, C will run havon on you if you try to use a dangling pointer */

	list_print(mt);

	return 0;
}
Exemplo n.º 17
0
/*
 * osprd_lock
 */
static int release_file_lock(struct file *filp)
{
  if (filp) {
    osprd_info_t *d = file2osprd(filp);
    int filp_writable = filp->f_mode & FMODE_WRITE;
    int filp_locked = filp->f_flags & F_OSPRD_LOCKED;

    if(filp_locked)
    {
      spin_lock(&d->mutex);

      if(filp_writable)
        d->num_write_locks--;
      else // file open for reading
        d->num_read_locks--;

      // Set the head to the next ticket so that some process may respond
      // Check for overflows, if the tail wraps around to 0, move the head to 0 as well.
      if(d->ticket_head < d->ticket_tail)
        d->ticket_head++;
      else if(d->ticket_head > d->ticket_tail)
        d->ticket_head = 0;

      d->lock_holder_l = list_remove_element(d->lock_holder_l, current->pid);
      spin_unlock(&d->mutex);

      // Clear the file's locked bit
      filp->f_flags &= ~F_OSPRD_LOCKED;

      wake_up_all(&d->blockq);
      return 0;
    }
  }

  return -EINVAL;
}
Exemplo n.º 18
0
/*
 * osprd_ioctl(inode, filp, cmd, arg)
 *   Called to perform an ioctl on the named file.
 */
int osprd_ioctl(struct inode *inode, struct file *filp,
		unsigned int cmd, unsigned long arg)
{
	osprd_info_t *d = file2osprd(filp);	// device info
	int r = 0;			// return value: initially 0

	// Set 'r' to the ioctl's return value: 0 on success, negative on error

	if (cmd == OSPRDIOCACQUIRE) {

		// EXERCISE: Lock the ramdisk.
		//
		// If *filp is open for writing (filp_writable), then attempt
		// to write-lock the ramdisk; otherwise attempt to read-lock
		// the ramdisk.
		//
        // This lock request must block using 'd->blockq' until:
		// 1) no other process holds a write lock;
		// 2) either the request is for a read lock, or no other process
		//    holds a read lock; and
		// 3) lock requests should be serviced in order, so no process
		//    that blocked earlier is still blocked waiting for the
		//    lock.
		//
		// If a process acquires a lock, mark this fact by setting
		// 'filp->f_flags |= F_OSPRD_LOCKED'.  You also need to
		// keep track of how many read and write locks are held:
		// change the 'osprd_info_t' structure to do this.
		//
		// Also wake up processes waiting on 'd->blockq' as needed.
		//
		// If the lock request would cause a deadlock, return -EDEADLK.
		// If the lock request blocks and is awoken by a signal, then
		// return -ERESTARTSYS.
		// Otherwise, if we can grant the lock request, return 0.

		// 'd->ticket_head' and 'd->ticket_tail' should help you
		// service lock requests in order.  These implement a ticket
		// order: 'ticket_tail' is the next ticket, and 'ticket_head'
		// is the ticket currently being served.  You should set a local
		// variable to 'd->ticket_head' and increment 'd->ticket_head'.
		// Then, block at least until 'd->ticket_tail == local_ticket'.
		// (Some of these operations are in a critical section and must
		// be protected by a spinlock; which ones?)

    // Used to track the current request
    unsigned local_ticket;

    if(check_deadlock(d))
		return -EDEADLK;

    // If we can't acquire the lock we put ourselves in the back of the queue
    // when the lock is released ticket_head will be incremented and we'll be
    // woken up
    while(try_acquire_file_lock(filp) != 0)
    {
      spin_lock(&d->mutex);
      d->ticket_tail++;
      local_ticket = d->ticket_tail;
      d->lock_waiter_l = list_add_to_front(d->lock_waiter_l, current->pid);
      spin_unlock(&d->mutex);

      wait_event_interruptible(d->blockq, d->ticket_head == local_ticket || d->num_to_requeue > 0);

      spin_lock(&d->mutex);
      d->lock_waiter_l = list_remove_element(d->lock_waiter_l, current->pid);
      spin_unlock(&d->mutex);

      // process any pending signals by re-queueing everything
      if(d->num_to_requeue > 0)
      {
        // Note: do NOT wake threads here, each thread should requeue only ONCE
        spin_lock(&d->mutex);
        d->num_to_requeue--;
        spin_unlock(&d->mutex);

        // If we find another pending signal, dispatch that too
        if(signal_pending(current))
          return -ERESTARTSYS;
      }
      else if(signal_pending(current)) // See if we were woken up by a signal
      {
        // For simplicity, we requeue all waiting tasks (-1 which
        // is the process) being "popped" off the wait queue
        spin_lock(&d->mutex);
        d->num_to_requeue = (d->ticket_tail - d->ticket_head - 1);
        d->ticket_head = 0;
        d->ticket_tail = 0;

        // All threads are woken to notify them of requeuing
        // meanwhile, we wait until that finishes (no need to check
        // for more interrupts, the process will exit anyway).
        wake_up_all(&d->blockq);
        spin_unlock(&d->mutex);

        // Sanity check
        if(d->num_to_requeue > 0)
        {
          wait_event(d->blockq, d->num_to_requeue == 0);
          wake_up_all(&d->blockq); // Wake everyone up again to check for other pending signals
        }
        return -ERESTARTSYS;
      }
    }

    r = 0;

	} else if (cmd == OSPRDIOCTRYACQUIRE) {

		// EXERCISE: ATTEMPT to lock the ramdisk.
		//
		// This is just like OSPRDIOCACQUIRE, except it should never
		// block.  If OSPRDIOCACQUIRE would block or return deadlock,
		// OSPRDIOCTRYACQUIRE should return -EBUSY.
		// Otherwise, if we can grant the lock request, return 0.

    r = try_acquire_file_lock(filp);

    if(r == -EDEADLK)
		r = -EBUSY;

	} else if (cmd == OSPRDIOCRELEASE) {

		// EXERCISE: Unlock the ramdisk.
		//
		// If the file hasn't locked the ramdisk, return -EINVAL.
		// Otherwise, clear the lock from filp->f_flags, wake up
		// the wait queue, perform any additional accounting steps
		// you need, and return 0.

		r = release_file_lock(filp);

	} else
		r = -ENOTTY; /* unknown command */
	return r;
}
Exemplo n.º 19
0
void stack_pop(stack_t *q) {
    if (q) list_remove_element(q, stack_top(q));
}
Exemplo n.º 20
0
void main()
{
	queue* myQueue = list_new();
	assert(myQueue);
	assert(myQueue->head->num == 0);
	assert(myQueue->tail->num == 0);
	
	printf("test no queue passed in\n");
	int ret = list_remove_element(NULL, 9);
	assert (ret == ULT_INVALID);
	
	/*
	printf("\ntest empty list\n");
	ret = list_remove_element(myQueue, 12);
	assert (ret == ULT_NONE);
	*/
	
	printf("\ntest add to invalid queue\n");
	ret = list_add_element(NULL);
	assert (ret == ULT_FAILED);
	
	printf("\ntest add 1 element\n");
	ret = list_add_element(myQueue);
	printf("first element after tid 0: %d\n", ret);
	assert (ULT_isOKRet(ret));
	
	printf("\ninside queue, %d elements\n", myQueue->numTCB);
	list_print(myQueue);
	list_print_backwards(myQueue);
	
	printf("\ntest add another element\n");
	ret = list_add_element(myQueue);
	printf("second element after tid 0: %d\n", ret);
	assert (ULT_isOKRet(ret));
	
	printf("\ninside queue, %d elements\n", myQueue->numTCB);
	list_print(myQueue);
	list_print_backwards(myQueue);
	
	//TESTS FOR LIST_REMOVE_HEAD
	printf("\ntest remove first element 3 times\n");
	ret = list_remove_head(myQueue);
	printf("element's tid: %d\n", ret);
	assert (ULT_isOKRet(ret));
	
	printf("\ninside queue, %d elements\n", myQueue->numTCB);
	list_print(myQueue);
	list_print_backwards(myQueue);
	
	ret = list_remove_head(myQueue);
	printf("element's tid: %d\n", ret);
	assert (ULT_isOKRet(ret));
	
	printf("\ninside queue, %d elements\n", myQueue->numTCB);
	list_print(myQueue);
	list_print_backwards(myQueue);
	
	ret = list_remove_head(myQueue);
	printf("element's tid: %d\n", ret);
	assert (ULT_isOKRet(ret));
	
	printf("\ninside queue, %d elements\n", myQueue->numTCB);
	list_print(myQueue);
	list_print_backwards(myQueue);
	
	printf("\ntest add another element after emptying queue\n");
	ret = list_add_element(myQueue);
	printf("element: %d\n", ret);
	assert (ULT_isOKRet(ret));
	
	printf("\ninside queue, %d elements\n", myQueue->numTCB);
	list_print(myQueue);
	list_print_backwards(myQueue);
	
	/*
	//TESTS FOR LIST_REMOVE_ELEMENT
	printf("\ntest remove third element\n");
	ret = list_remove_element(myQueue, 2);
	printf("element's tid: %d\n", ret);
	assert (ULT_isOKRet(ret));
	
	printf("\ninside queue, %d elements\n", myQueue->numTCB);
	list_print(myQueue);
	list_print_backwards(myQueue);
	
	printf("\ntest remove second element\n");
	ret = list_remove_element(myQueue, 1);
	printf("element's tid: %d\n", ret);
	assert (ULT_isOKRet(ret));
	
	printf("\ninside queue, %d elements\n", myQueue->numTCB);
	list_print(myQueue);
	list_print_backwards(myQueue);
	
	printf("\ntest remove first element\n");
	ret = list_remove_element(myQueue, 0);
	printf("element's tid: %d\n", ret);
	assert (ULT_isOKRet(ret));
	
	printf("\ninside queue, %d elements\n", myQueue->numTCB);
	list_print(myQueue);
	list_print_backwards(myQueue);
	
	printf("\ntest remove no more elements\n");
	ret = list_remove_element(myQueue, 1);
	printf("element's tid: %d\n", ret);
	assert (ret == ULT_INVALID);
	
	printf("\ntest add another element after emptying list\n");
	ret = list_add_element(myQueue);
	printf("element: %d\n", ret);
	assert (ULT_isOKRet(ret));
	
	printf("\ninside queue, %d elements\n", myQueue->numTCB);
	list_print(myQueue);
	list_print_backwards(myQueue);
	
	printf("\ntest add 2nd element after emptying list\n");
	ret = list_add_element(myQueue);
	printf("element: %d\n", ret);
	assert (ULT_isOKRet(ret));
	
	printf("\ninside queue, %d elements\n", myQueue->numTCB);
	list_print(myQueue);
	list_print_backwards(myQueue);
	
	printf("\ntest add 3rd element after emptying list\n");
	ret = list_add_element(myQueue);
	printf("element: %d\n", ret);
	assert (ULT_isOKRet(ret));
	
	printf("\ninside queue, %d elements\n", myQueue->numTCB);
	list_print(myQueue);
	list_print_backwards(myQueue);
	
	printf("\ntest remove second element AGAIN\n");
	ret = list_remove_element(myQueue, 1);
	printf("element's tid: %d\n", ret);
	assert (ULT_isOKRet(ret));
	
	printf("\ninside queue, %d elements\n", myQueue->numTCB);
	list_print(myQueue);
	list_print_backwards(myQueue);
	*/
}
Exemplo n.º 21
0
void list_free_all (pid_list_t head)
{
	while (head != NULL)
		head = list_remove_element(head, head->pid);
}
Exemplo n.º 22
0
int osprd_ioctl(struct inode *inode, struct file *filp,
		unsigned int cmd, unsigned long arg)
{
	osprd_info_t *d = file2osprd(filp);	// device info
	int r = 0;			// return value: initially 0
	unsigned cur_ticket;
	// is file open for writing?
	int filp_writable = (filp->f_mode & FMODE_WRITE) != 0;

	// This line avoids compiler warnings; you may remove it.
	(void) filp_writable, (void) d;

	// Set 'r' to the ioctl's return value: 0 on success, negative on error

	eprintk("%d\n", (int)current->pid);
	if (cmd == OSPRDIOCACQUIRE) {

		// EXERCISE: Lock the ramdisk.
		osp_spin_lock(&d->mutex);
		
		if (check_deadlock(d)) 
		{
			//osp_spin_unlock(&d->mutex);
			//return -EDEADLK;
			r = -EDEADLK;
		}
		else

		{
			add_check_deadlock_list(current->pid, d);
			eprintk ("add_check_deadlock_list");
			cur_ticket = d->ticket_head;
			d->ticket_head ++ ;
		}
		osp_spin_unlock(&d->mutex);
		if (r != 0) {
			return r;
		}

		if(filp_writable)
		{
			//osp_spin_lock(&d->mutex);	
			int w = wait_event_interruptible(d->blockq, (d->number_write_lock==0&&d->number_read_lock==0&&cur_ticket==d->ticket_tail));
			//Blocks the current task on a wait queue until a CONDITION becomes true. 
			//A request for a write lock on a ramdisk file will block until no other files on that 
			//ramdisk have a read or writeloc
			if(w == -ERESTARTSYS)
			{
				osp_spin_lock(&d->mutex);	
				//if the process is interrupted by signal
				if (cur_ticket == d->ticket_tail)
					d->ticket_tail++;
				//already in the next avalable ticket
				else
					d->ticket_head--;
				//destory this ticket
				osp_spin_unlock(&d->mutex);	
				return w;
			}
			
			osp_spin_lock(&d->mutex);	
			//Acquire a mutex (lock the mutex)
			d->ticket_tail++;
			d->write_lock_holder = current->pid;
			d->number_write_lock = 1;
			filp->f_flags |= F_OSPRD_LOCKED;
			osp_spin_unlock(&d->mutex);	
			//Release (unlock) the mutex
		}
		else
		{

			int w = wait_event_interruptible(d->blockq, (d->number_write_lock==0&&cur_ticket==d->ticket_tail));
			//Blocks the current task on a wait queue until a CONDITION becomes true. 
			//A request for a write lock on a ramdisk file will block until no other files on that 
			//ramdisk have a read or writeloc
			if(w == -ERESTARTSYS)
			{
				osp_spin_lock(&d->mutex);
				//if the process is interrupted by signal
				if (cur_ticket == d->ticket_tail)
					d->ticket_tail++;
				//already in the next avalable ticket
				else
					d->ticket_head--;
				osp_spin_unlock(&d->mutex);	
				//destory this ticket
				return w;
			}
			
			osp_spin_lock(&d->mutex);	
			//Acquire a mutex (lock the mutex)
			d->ticket_tail++;
			add_read_pid(current->pid,d);
			d->number_read_lock++;
			filp->f_flags |= F_OSPRD_LOCKED;
			osp_spin_unlock(&d->mutex);	
			//Release (unlock) the mutex
		}

	} else if (cmd == OSPRDIOCTRYACQUIRE) {

		// EXERCISE: ATTEMPT to lock the ramdisk.
		//
		// This is just like OSPRDIOCACQUIRE, except it should never
		// block.  If OSPRDIOCACQUIRE would block or return deadlock,
		// OSPRDIOCTRYACQUIRE should return -EBUSY.
		// Otherwise, if we can grant the lock request, return 0.

		// Your code here (instead of the next two lines).
		if (filp_writable)
		{
			//atomically acquire write lock
			osp_spin_lock (&d->mutex);	//atomicity
			if ((d->number_read_lock >0) || (d->number_write_lock>0))
			{
				osp_spin_unlock (&d->mutex);
				return -EBUSY;
			}
			else 	//d->number_read_lock ==0) && (d->number_write_lock==0)
			{
				d->write_lock_holder = current->pid;
				d->number_write_lock ++;
				d->ticket_tail++;
				d->ticket_head++;
				filp -> f_flags |= F_OSPRD_LOCKED;
				osp_spin_unlock (&d->mutex);
			}
		}
		else 	//opened for read 
		{
			//atomically acquire read lock
			osp_spin_lock (&d->mutex);
			{
				if (d->number_write_lock>0)		//can't get read lock
				{
					osp_spin_unlock(&d->mutex);
					return -EBUSY;
				}
				else
				{
					add_read_pid (current->pid,d);
					d->number_read_lock++;
					d->ticket_tail++;
					d->ticket_head++;
					filp -> f_flags |= F_OSPRD_LOCKED;
					osp_spin_unlock (&d->mutex);
				}
			}
		}

		
		//eprintk("Attempting to try acquire\n");
		//r = -ENOTTY;

	} else if (cmd == OSPRDIOCRELEASE) {

		// EXERCISE: Unlock the ramdisk.
		//
		// If the file hasn't locked the ramdisk, return -EINVAL.
		// Otherwise, clear the lock from filp->f_flags, wake up
		// the wait queue, perform any additional accounting steps
		// you need, and return 0.
		//osp_spin_lock (&d->mutex);
		if ((filp->f_flags & F_OSPRD_LOCKED)==0)
		{
			//osp_spin_unlock (&d->mutex);
			return -EINVAL;
		}
		else
		{
			osp_spin_lock (&d->mutex);	
			d->check_deadlock_list_head = list_remove_element(d->check_deadlock_list_head,current->pid);
			if (filp_writable)		//release the write locker
			{
				d->write_lock_holder = -1;
				d->number_write_lock --;
			}
			else 	//release the read locker
			{
				d->number_read_lock --;
				d->pid_list_head = list_remove_element(d->pid_list_head,current->pid);
				/*if (list_free_all (pid_list_head) == -ENOTTY)
					return -ENOTTY;*/
				if (d->pid_list_head == NULL)
					return -ENOTTY;
			}
			filp->f_flags &= ~F_OSPRD_LOCKED; 
			
			osp_spin_unlock (&d->mutex);
			wake_up_all (&d->blockq);

		}
		// Your code here (instead of the next line).
		//r = -ENOTTY;

	}
	else
		r = -ENOTTY; /* unknown command */
	return r;

}