/* procedure to poll the event queue for timer events, run by the clock
   thread; on a timer event, call "send_interrupt()" to run the system thread's
   clock handler routine 
*/
DWORD WINAPI clock_poll(LPVOID arg) {
#ifdef WINCE
  for(;;) {	
  Sleep(PERIOD/1000); /* sleep requires time in milliseconds */
  send_interrupt(CLOCK_INTERRUPT_TYPE, NULL);
  }
#else
  LARGE_INTEGER i;
  HANDLE timer; 
  /* HANDLE thread = GetCurrentThread(); */
  char name[64];

  sprintf(name, "timer %d", pid);
  timer = CreateWaitableTimer(NULL, TRUE, name);
  assert(timer != NULL);

  for (;;) {
    i.QuadPart = -PERIOD*10; /* NT timer values are in hundreds of nanoseconds */
    AbortOnError(SetWaitableTimer(timer, &i, 0, NULL, NULL, FALSE));

    if (WaitForSingleObject(timer, INFINITE) == WAIT_OBJECT_0) {
      if (DEBUG)
	kprintf("CLK: clock tick.\n");
      send_interrupt(CLOCK_INTERRUPT_TYPE, NULL);
    }
  }
#endif
  /* never reached */
  return 0;

}
Ejemplo n.º 2
0
/* Basically, this function is guaranteed to return
 * when the target CPU/scheduler is locked for you to
 * use.
 */
void sched_lock( int cpu_id, int complete )
{
	int lock = 0;
	
	assert( (cpu_id >= 0) && (cpu_id < cpu_count) );
	assert( ! ((CPUID == cpu_id) && (complete == 1 )) );	
				// Because a complete lock requires the scheduler to halt
				// the running thread. But if the thread is running on the
				// same CPU and it's halted, then we're in trouble.

	//if ( CPUID == cpu_id ) lock = disable_interrupts();
	lock = disable_interrupts();
	
	acquire_spinlock( &(cpu[ cpu_id ].sched.lock_scheduler) );
	cpu[ cpu_id ].sched.lock_flags = lock;
	

	// If it's idle, wake it up..
	if ( cpu[ cpu_id ].sched.idle != 0 )
	{
		// Mark it as not-idle and wake it up.
		cpu[ cpu_id ].sched.idle = 0;
		send_interrupt( cpu_id, APIC_INTERRUPT );
	}
	

	if ( complete == 1 )
	{
		while ( cpu[ cpu_id ].sched.running != 0 );
	}


	assert( cpu[ cpu_id ].sched.nested_lock++ == 0 );
}
Ejemplo n.º 3
0
int WINAPI read_poll(void* arg) {
	
	struct kb_line* new_node;

	while (1) {
		new_node = (struct kb_line*) malloc(sizeof(struct kb_line));
		new_node->next = NULL;

		fgets(new_node->buf, MAX_LINE_LENGTH, stdin);
	
#ifdef WINCE
		if(new_node->buf[0] != 0) 
		    send_interrupt(READ_INTERRUPT_TYPE, new_node);
#else
		send_interrupt(READ_INTERRUPT_TYPE, new_node);
#endif
	}
}
Ejemplo n.º 4
0
static void check_timeout(int index)
{
	struct timeval tv;

	if (!eth_timeout_flags[index]) return;
	if (gettimeofday(&tv, NULL) != 0) return;
	if (TIMEVAL_CMP(tv, eth_timeout[index]) < 1) return;

	send_interrupt(index);

	eth_timeout_flags[index] = 0;
}
Ejemplo n.º 5
0
int read_poll(void* arg) {

	struct kb_line* new_node;

	while (1) {
		new_node = (struct kb_line*) malloc(sizeof(struct kb_line));
		new_node->next = NULL;

		fgets(new_node->buf, MAX_LINE_LENGTH, stdin);

		send_interrupt(READ_INTERRUPT_TYPE, read_handler, new_node);
	}
}
/* procedure to poll the event queue for timer events, run by the clock
   thread; on a timer event, call "send_interrupt()" to run the system thread's
   clock handler routine 
*/
DWORD WINAPI clock_poll(LPVOID arg) {
#ifdef WINCE
  Sleep(PERIOD/1000); /* sleep requires time in milliseconds */
  send_interrupt(CLOCK_INTERRUPT_TYPE, NULL);
#else
  LARGE_INTEGER i;
  HANDLE timer; 
  /* HANDLE thread = GetCurrentThread(); */
  char name[32];

  sprintf(name, "timer %d", pid);
  timer = CreateWaitableTimer(NULL, TRUE, name);
  assert(timer != NULL);

  WaitOnObject(clock_poll_done);
  while (clock_enabled) {
    i.QuadPart = -PERIOD*10; /* NT timer values are in hundreds of nanoseconds */
    AbortOnError(SetWaitableTimer(timer, &i, 0, NULL, NULL, FALSE));

    if (WaitForSingleObject(timer, INFINITE) == WAIT_OBJECT_0) {
      //if (DEBUG)
	//kprintf("CLK: clock tick.\n");
	  ticks++;
	  clock_enabled ? send_interrupt(CLOCK_INTERRUPT_TYPE, NULL): clock_enabled;
    }
  }

  dbgprintf("...clock interrupts stopped.\n");

  ReleaseMutex(clock_poll_done);

#endif

  return 0;

}
/* 
 * receive incoming packets from the specified socket, translate their 
 * addresses to network_address_t type, and call the user-supplied handler
 *
 * a network interrupt disables interrupts, so that we can cleanly return.
 * if interrupts were not disabled, and we were hit by a clock interrupt, it
 * would not be possible to return until we returned to the original stack.
 * this is inelegant, but we are constrained by ignorance of the minithread
 * struct format!
*/
int WINAPI network_poll(void* arg) {
  SOCKET* s;
  network_interrupt_arg_t* packet;
  struct sockaddr_in addr;
  int fromlen = sizeof(struct sockaddr_in);

  s = (SOCKET *) arg;

  for (;;) {

    /* we rely on run_user_handler to destroy this data structure */
    if (DEBUG)
      kprintf("NET:Allocating an incoming packet.\n");

    packet = 
      (network_interrupt_arg_t *) malloc(sizeof(network_interrupt_arg_t));
    assert(packet != NULL);
  
    packet->size = recvfrom(*s, packet->buffer, MAX_NETWORK_PKT_SIZE,
			    0, (struct sockaddr *) &addr, &fromlen);
    if (packet->size <= 0) {
      if(WSAGetLastError() == 10054){
        kprintf("NET: Broadcst attempt rejected (Are all my neighbors running?)\n");
        free(packet);
        continue;
      } else {
        kprintf("NET:Error, %d.\n", WSAGetLastError());
        AbortOnCondition(1,"Crashing.");
      }
    }
    else if (DEBUG)
      kprintf("NET:Received a packet, seqno %ld.\n", ntohl(*((int *) packet->buffer)));
   
    assert(fromlen == sizeof(struct sockaddr_in));
    sockaddr_to_network_address(&addr, packet->addr);

    /* 
     * now we have filled in the arg to the network interrupt service routine,
     * so we have to get the user's thread to run it.
     */
    if (DEBUG)
      kprintf("NET:packet arrived.\n");
    send_interrupt(NETWORK_INTERRUPT_TYPE, (void*)packet);
  }	
}
Ejemplo n.º 8
0
int
network_poll(void* arg)
{
    int* s;
    network_interrupt_arg_t* packet;
    struct sockaddr_in addr;
    int fromlen = sizeof(struct sockaddr_in);

    s = (int *) arg;

    for (;;) {

        /* we rely on run_user_handler to destroy this data structure */
        if (DEBUG)
            kprintf("NET:Allocating an incoming packet.\n");

        packet =
            (network_interrupt_arg_t *) malloc(sizeof(network_interrupt_arg_t));
        assert(packet != NULL);

        packet->size = recvfrom(*s, packet->buffer, MAX_NETWORK_PKT_SIZE,
                                0, (struct sockaddr *) &addr, (socklen_t*) &fromlen);
        if (packet->size < 0) {
            kprintf("NET:Error, %d.\n", errno);
            AbortOnCondition(1,"Crashing.");
        } else if (DEBUG)
            kprintf("NET:Received a packet, seqno %ld.\n",
                    (long) ntohl(*((int *) packet->buffer)));

        assert(fromlen == sizeof(struct sockaddr_in));
        sockaddr_to_network_address(&addr, packet->addr);

        /*
         * now we have filled in the arg to the network interrupt service routine,
         * so we have to get the user's thread to run it.
         */
        if (DEBUG)
            kprintf("NET:packet arrived.\n");
        send_interrupt(NETWORK_INTERRUPT_TYPE, (void*)packet);
    }
}
Ejemplo n.º 9
0
/* handle read and write to disk. Watch the job queue and
   submit the requests to the operating system one by one.
   On completion, the user suplied function with the user
   suplied parameter is called

   The interrupt mechanism is used much like in the network
   case. One such process per disk.

   The argument is a disk_t with the disk description.
 */
void disk_poll(void* arg) {
    enum { DISK_OK, DISK_CRASHED } disk_state;

    disk_t* disk = (disk_t*) arg;
    disk_layout_t layout;

    disk_interrupt_arg_t* disk_interrupt;
    disk_queue_elem_t* disk_request;

    disk_state=DISK_OK;

    for (;;){
        int blocknum;
        char* buffer;
        disk_request_type_t type;
        int offset;

        /* We use mutex to protect queue handling, as should
           the code that inserts requests in the queue
         */

        /* wait for somebody to put something in the queue */
        sem_wait(&disk->semaphore);

        if (DEBUG)
            kprintf("Disk Controler: got a request.\n");

        /* get exclusive access to queue handling  and dequeue a request */
        pthread_mutex_lock(&disk_mutex);

        layout = disk->layout; /* this is the layout used until the request is fulfilled */
        /* this is safe since a disk can only grow */

        if (disk->queue != NULL){
            disk_interrupt = (disk_interrupt_arg_t*)
                malloc(sizeof(disk_interrupt_arg_t));
            assert( disk_interrupt != NULL);

            disk_interrupt->disk = disk;
            /* we look first at the first request in the queue
               to see if it is special.
             */
            disk_interrupt->request =
                disk->queue->request;

            /* check if we shut down the disk */
            if (disk->queue->request.type == DISK_SHUTDOWN){
                if (DEBUG)
                    kprintf("Disk: Shutting down.\n");

                disk_interrupt->reply=DISK_REPLY_OK;
                fclose(disk->file);
                pthread_mutex_unlock(&disk_mutex);
                sem_destroy(&disk->semaphore);
                send_interrupt(DISK_INTERRUPT_TYPE, mini_disk_handler, (void*)disk_interrupt);
                break; /* end the disk task */
            }

            /* check if we got to reset the disk */
            if (disk->queue->request.type == DISK_RESET){
                disk_queue_elem_t* curr;
                disk_queue_elem_t *next;

                if (DEBUG)
                    kprintf("Disk: Resetting.\n");

                disk_interrupt->reply=DISK_REPLY_OK;
                /* empty the queue */
                curr=disk->queue;
                while (curr!=NULL){
                    next=curr->next;
                    free(curr);
                    curr=next;
                }
                disk->queue = disk->last = NULL;

                disk_state = DISK_OK;
                pthread_mutex_unlock(&disk_mutex);
                goto sendinterrupt;
            }

            /* permute the first two elements in the queue
               probabilistically if queue has two elements
             */
            if (disk->queue->next !=NULL &&
                    (genrand() < reordering_rate)){
                disk_queue_elem_t* first = disk->queue;
                disk_queue_elem_t* second = first->next;
                first->next = second->next;
                second->next = first;
                disk->queue = second;
                if (disk->last == second)
                    disk->last = first;
            }

            /* dequeue the first request */
            disk_request = disk->queue;
            disk->queue = disk_request->next;
            if (disk->queue == NULL)
                disk->last = NULL;
        } else {
            /* empty queue, release the lock and leave */
            pthread_mutex_unlock(&disk_mutex);
            break;
        }

        pthread_mutex_unlock(&disk_mutex);

        disk_interrupt->request = disk_request->request;

        /* crash the disk ocasionally */
        if (genrand() < crash_rate){
            disk_state = DISK_CRASHED;

            /*      if (DEBUG) */
            kprintf("Disk: Crashing disk.\n");

        }

        /* check if disk crashed */
        if (disk_state == DISK_CRASHED){
            disk_interrupt->reply=DISK_REPLY_CRASHED;
            goto sendinterrupt;
        }

        if ( genrand() < failure_rate ) {
            /* Trash the request */
            disk_interrupt->reply = DISK_REPLY_FAILED;

            if (DEBUG)
                kprintf("Disk: Request failed.\n");

            goto sendinterrupt;
        }

        /* Check validity of request */

        disk_interrupt->reply = DISK_REPLY_OK;

        blocknum = disk_request->request.blocknum;
        buffer = disk_request->request.buffer;
        type = disk_request->request.type;

        if (DEBUG)
            kprintf("Disk Controler: got a request for block %d type %d .\n",
                    blocknum, type);

        /* If we got here is a read or a write request */

        offset = DISK_BLOCK_SIZE*(blocknum + 1);

        if ( (blocknum >= layout.size) ||
                (fseek(disk->file, offset, SEEK_SET) != 0) ) {
            disk_interrupt->reply = DISK_REPLY_ERROR;

            if (DEBUG)
                kprintf("Disk Controler: Block too big or failed fseek, block=%d,  offset=%d, disk_size=%d.\n",
                        blocknum, offset, layout.size);

            goto sendinterrupt;
        }

        switch (type) {
            case DISK_READ:
                if (fread(buffer, 1, DISK_BLOCK_SIZE, disk->file)
                        < DISK_BLOCK_SIZE)
                    disk_interrupt->reply = DISK_REPLY_ERROR;
                if (DEBUG)
                    kprintf("Disk: Read request.\n");

                break;
            case DISK_WRITE:
                if (fwrite(buffer, 1, DISK_BLOCK_SIZE, disk->file)
                        < DISK_BLOCK_SIZE)
                    disk_interrupt->reply = DISK_REPLY_ERROR;
                fflush(disk->file);
                if (DEBUG)
                    kprintf("Disk: Write request.\n");

                break;
            default:
                break;
        }

sendinterrupt:
        if (DEBUG)
            kprintf("Disk Controler: sending an interrupt for block %d, request type %d, with reply %d.\n",
                    disk_interrupt->request.blocknum,
                    disk_interrupt->request.type,
                    disk_interrupt->reply);

        send_interrupt(DISK_INTERRUPT_TYPE, mini_disk_handler, (void*)disk_interrupt);
    }

}
Ejemplo n.º 10
0
int
canon(char *ep, int c)
{
	if(c&0200)
		return(SCROLL);
	switch(c) {
		case '\b':
			if(sendp > sendbuf)
				sendp--;
			*ep++ = '\b';
			*ep++ = ' ';
			*ep++ = '\b';
			break;
		case 0x15:	/* ^U line kill */
			sendp = sendbuf;
			*ep++ = '^';
			*ep++ = 'U';
			*ep++ = '\n';
			break;
		case 0x17:	/* ^W word kill */
			while(sendp > sendbuf && !alnum(*sendp)) {
				*ep++ = '\b';
				*ep++ = ' ';
				*ep++ = '\b';
				sendp--;
			}
			while(sendp > sendbuf && alnum(*sendp)) {
				*ep++ = '\b';
				*ep++ = ' ';
				*ep++ = '\b';
				sendp--;
			}
			break;
		case '\177':	/* interrupt */
			sendp = sendbuf;
			send_interrupt();
			return(NEWLINE);
		case '\021':	/* quit */
		case '\r':
		case '\n':
			if(sendp < &sendbuf[512])
				*sendp++ = '\n';
			sendnchars((int)(sendp-sendbuf), sendbuf);
			sendp = sendbuf;
			if(c == '\n' || c == '\r') {
				*ep++ = '\n';
			}
			*ep = 0;
			return(NEWLINE);
		case '\004':	/* EOT */
			if(sendp == sendbuf) {
				sendnchars(0,sendbuf);
				*ep = 0;
				return(NEWLINE);
			}
			/* fall through */
		default:
			if(sendp < &sendbuf[512])
				*sendp++ = c;
			*ep++ = c;
			break;

	}
	*ep = 0;
	return(OTHER);
}