int * parse_into_shared_int_array(char *line, unsigned *array_size)
{
  // Use linked list to buffer the integers
  int_list list;
  int_list_init(&list);

  char *temp;
  char *token = strtok(line, " ");
  while (token)
  {
    int_list_add(&list, (int) strtol(token, &temp, 10));
    token = strtok(NULL, " ");
  }

  *array_size = list.size;

  // Initialize shared memory.
  void *array = 0;
  if ((array = mmap(0, list.size * sizeof(int), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0)) == 0)
  {
    printf("ERROR: failed to initailize shared memory.\n");
    return 0;
  }
  
  int *int_array = (int *) array;

  int i = 0;
  while (list.head)
  {
    int_array[i++] = list.head->data;
    int_list_remove(&list, list.head->data);
  }

  return int_array;
}
/* a, a-b, or a-b:c */
static int parse_range(char_stream_t cs, int_list_t il) {
  int a = parse_int(cs);
  if (a == -1) return 0;	/* NG */
  int b = a + 1;
  int c = 1;			/* stride */
  int x;
  if (cur_char(cs) == '-') {
    next_char(cs);
    b = parse_int(cs);
    if (b == -1) return 0;
    if (cur_char(cs) == ':') {
      next_char(cs);
      c = parse_int(cs);
      if (c == -1) return 0; /* NG */
    }
  } 
  for (x = a; x < b; x += c) {
    if (!int_list_add(il, x)) {
      parse_error(cs, 
		  "myth_parse_cpu_list: too many numbers in MYTH_CPU_LIST\n");
      return 0;
    }
  }
  return 1;			/* OK */
}
Exemple #3
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

	// is file open for writing?
	int filp_writable = (filp->f_mode & FMODE_WRITE) != 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?)

        unsigned my_ticket;
        int ret;

        osp_spin_lock(&d->mutex);

        /* Check for deadlock: can't acquire r/w lock if already locked by this process */
        if (int_list_contains(d->read_lock_list, current->pid) ||
            d->write_lock_pid == current->pid)
        {
            osp_spin_unlock(&d->mutex);
            return -EDEADLK;
        }

        /* Increment ticket_head after checking for deadlock, or else ticket becomes invalid */
        my_ticket = d->ticket_head++;

        /* If write lock request, must wait until no more read locks AND no more write locks;
           if read lock request, wait until no more write locks. */
        if (filp_writable)
        {
            osp_spin_unlock(&d->mutex);
            ret = wait_event_interruptible(d->blockq, d->ticket_tail == my_ticket &&
                        int_list_empty(d->read_lock_list) &&
                        d->write_lock_pid == -1);
            if (!ret)
            {
                /* Set device to locked, indicate that this process holds the write lock,
                   and advance d->ticket_tail. */
                osp_spin_lock(&d->mutex);

                filp->f_flags |= F_OSPRD_LOCKED;
                d->write_lock_pid = current->pid;
                advance_to_next_valid_ticket(d);

                osp_spin_unlock(&d->mutex);
            }
            else        /* Woken up by signal */
            {
                /* If ticket_tail == this thread's ticket, advance to next valid ticket;
                   otherwise, mark this thread's ticket as invalid */
SIGNAL_WAKE_UP:
                if (d->ticket_tail == my_ticket)
                {
                    osp_spin_lock(&d->mutex);
                    advance_to_next_valid_ticket(d);
                    osp_spin_unlock(&d->mutex);
                }
                else
                {
                    osp_spin_lock(&d->mutex);
                    int_list_add(d->invalid_tickets, my_ticket);
                    osp_spin_unlock(&d->mutex);
                }
                return -ERESTARTSYS;
            }
        }
        else
        {
            osp_spin_unlock(&d->mutex);
            ret = wait_event_interruptible(d->blockq, d->ticket_tail == my_ticket &&
                        d->write_lock_pid == -1);
            if (!ret)
            {
                /* Set device to locked, indicate that this process holds a read lock,
                   and advance d->ticket_tail. */
                osp_spin_lock(&d->mutex);

                filp->f_flags |= F_OSPRD_LOCKED;
                int_list_add(d->read_lock_list, current->pid);
                advance_to_next_valid_ticket(d);

                osp_spin_unlock(&d->mutex);
                wake_up_all(&d->blockq);
            }
            else        /* Woken up by signal */
                goto SIGNAL_WAKE_UP;
        }
        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.

        osp_spin_lock(&d->mutex);

        /* Check for deadlock normally */
        if (int_list_contains(d->read_lock_list, current->pid) ||
            d->write_lock_pid == current->pid)
        {
            osp_spin_unlock(&d->mutex);
            return -EBUSY;
        }
        /* Check for lock acquire conditions:
            - ticket_tail must equal ticket_head
            - there must be no write lock
            - if write lock request, must be no read locks */
        if (d->ticket_head != d->ticket_tail || d->write_lock_pid != -1)
        {
            osp_spin_unlock(&d->mutex);
            return -EBUSY;
        }
        if (filp_writable && !int_list_empty(d->read_lock_list))
        {
            osp_spin_unlock(&d->mutex);
            return -EBUSY;
        }

        /* Acquire the read/write lock */
        if (filp_writable)
            d->write_lock_pid = current->pid;
        else
            int_list_add(d->read_lock_list, current->pid);
        filp->f_flags |= F_OSPRD_LOCKED;

        osp_spin_unlock(&d->mutex);
        wake_up_all(&d->blockq);
        r = 0;

	} 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.

        /* Same as release procedure in osprd_close_last() */
        osp_spin_lock(&d->mutex);

        if (try_release_lock(d, filp, filp_writable))
        {
            osp_spin_unlock(&d->mutex);
            wake_up_all(&d->blockq);
        }
        else
        {
            osp_spin_unlock(&d->mutex);
        }
		r = 0;

	} else
		r = -ENOTTY; /* unknown command */
	return r;
}
Exemple #4
0
char *test_has_int_1(){
    IntList *il = create_int_list();
    int_list_add(il, 1);
    mu_assert(il->first->i == 1, "La lista de enteros tiene al elemento 1");
    return NULL;
}