void start_disk_poll(disk_t* disk){ //int id; pthread_t disk_thread; sigset_t set; struct sigaction sa; sigset_t old_set; sigemptyset(&set); sigaddset(&set,SIGRTMAX-1); sigaddset(&set,SIGRTMAX-2); sigprocmask(SIG_BLOCK,&set,&old_set); sa.sa_handler = (void*)handle_interrupt; sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK; sa.sa_sigaction= (void*)handle_interrupt; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask,SIGRTMAX-2); sigaddset(&sa.sa_mask,SIGRTMAX-1); if (sigaction(SIGRTMAX-2, &sa, NULL) == -1) AbortOnError(0); /* reset the request queue */ disk->queue = disk->last = NULL; /* create request semaphore */ AbortOnCondition(sem_init(&disk->semaphore, 0, 0),"sem_init"); AbortOnCondition(pthread_create(&disk_thread, NULL, (void*)disk_poll, (void*)disk), "pthread"); pthread_sigmask(SIG_SETMASK,&old_set,NULL); }
int hostname_to_entry(bcast_t* bcast, char* hostname) { network_address_t addr; unsigned int ipaddr; int entry = -1; int i; if (hostname == NULL) return bcast->me; if (network_translate_hostname(hostname, addr) != 0) { kprintf("Error: could not resolve host name.\n"); AbortOnCondition(1,"Crashing."); } ipaddr = addr[0]; for (i=0; i<bcast->n_entries; i++) if (ipaddr == bcast->entries[i].addr[0]) entry = i; AbortOnCondition(entry == -1, "Error: host name not in broadcast table."); return entry; }
void semaphore_destroy(semaphore_t *sem) { //Validate input arguments, abort if invalid argument is seen AbortOnCondition(sem == NULL, "Null argument sem in semaphore_destroy()"); assert(sem->semaWaitQ != NULL); //sanity check interrupt_level_t old_level = set_interrupt_level(DISABLED); //disable interruption //critical section int freeQueueSuccess = queue_free(sem->semaWaitQ); //release waiting queue AbortOnCondition(freeQueueSuccess != 0, "Free Queue failed in semaphore_destroy()"); free(sem); //release semaphore set_interrupt_level(old_level); //restore interruption level }
void bcast_initialize(char* configfile, bcast_t* bcast) { FILE* config = fopen(configfile, "r"); char line[BCAST_MAX_LINE_LEN]; int i = 0; char* rv; network_address_t my_addr; unsigned int my_ip_addr; network_get_my_address(my_addr); my_ip_addr = my_addr[0]; while ((rv = fgets(line, BCAST_MAX_LINE_LEN, config)) != NULL) { if (line[0] == '\r' || line[0] == '\n') break; line[strlen(line)-1] = '\0'; strcpy(bcast->entries[i].name, line); bcast->entries[i].n_links = 0; if (network_translate_hostname(line, bcast->entries[i].addr) != 0) { kprintf("Error: could not resolve hostname %s.\n", line); AbortOnCondition(1,"Crashing."); } if (bcast->entries[i].addr[0] == my_ip_addr) bcast->me = i; i++; } bcast->n_entries = i; if (rv != NULL) for (i=0; i<bcast->n_entries; i++) { //int len; int j; AbortOnCondition(fgets(line, BCAST_MAX_LINE_LEN, config) == NULL, "Error: incomplete adjacency matrix."); //len = strlen(line); for (j=0; j<bcast->n_entries; j++) if (i == j) ; /* avoid self-links */ else if (line[j] != '.') { bcast->entries[i].links[bcast->entries[i].n_links] = j; bcast->entries[i].n_links++; } } fclose(config); }
int transmit(int* arg) { char buffer[BUFFER_SIZE]; int length; int i; network_address_t addr; miniport_t port; miniport_t dest; AbortOnCondition(network_translate_hostname(hostname, addr) < 0, "Could not resolve hostname, exiting."); port = miniport_local_create(0); dest = miniport_remote_create(addr, 0); for (i=0; i<MAX_COUNT; i++) { printf("Sending packet %d.\n", i+1); sprintf(buffer, "Count is %d.\n", i+1); length = strlen(buffer) + 1; minimsg_send(port, dest, buffer, length); } miniport_destroy(port); return 0; }
int miniterm_initialize() { pthread_t read_thread; sigset_t set; sigset_t old_set; sigfillset(&set); sigprocmask(SIG_BLOCK,&set,&old_set); kprintf("Starting read interrupts.\n"); mini_read_handler = read_handler; kb_head = NULL; kb_tail = NULL; new_data = semaphore_create(); semaphore_initialize(new_data, 0); AbortOnCondition(pthread_create(&read_thread, NULL, (void*)read_poll, NULL)!=0, "pthread"); sigdelset(&old_set,SIGRTMAX-2); sigdelset(&old_set,SIGRTMAX-1); pthread_sigmask(SIG_SETMASK,&old_set,NULL); return 0; }
int transmit1(int* arg) { char buffer[BUFFER_SIZE]; int length; int i; network_address_t addr; miniport_t port; miniport_t dest; AbortOnCondition(network_translate_hostname(hostname, addr) < 0, "Could not resolve hostname, exiting."); port = miniport_create_unbound(0); dest = miniport_create_bound(addr, 1); for (i=MAX_COUNT/2; i<MAX_COUNT; i++) { printf("Sending packet %d.\n", i+1); sprintf(buffer, "Count is %d.\n", i+1); length = strlen(buffer) + 1; minimsg_send(port, dest, buffer, length); minithread_yield(); } return 0; }
void minimsg_network_handler(network_interrupt_arg_t* arg) { interrupt_level_t old_level = set_interrupt_level(DISABLED); //disable interrupt //Get header and destination port mini_header_t receivedHeader; memcpy(&receivedHeader, arg->buffer, sizeof(mini_header_t)); int destPort = (int)unpack_unsigned_short(receivedHeader.destination_port); assert(destPort >= UNBOUNDED_PORT_START && destPort <= UNBOUNDED_PORT_END); // sanity checking //if the unbounded port has not been initialized, throw away the packet if (g_unboundedPortPtrs[destPort] == NULL) { set_interrupt_level(old_level); //restore interrupt level return; } //queue the packet and V the semaphore assert(g_unboundedPortPtrs[destPort]->port_type == 'u' && g_unboundedPortPtrs[destPort]->unbound_port.datagrams_ready != NULL && g_unboundedPortPtrs[destPort]->unbound_port.incoming_data != NULL); int appendSuccess = queue_append(g_unboundedPortPtrs[destPort]->unbound_port.incoming_data, (void*)arg); AbortOnCondition(appendSuccess == -1, "Queue_append failed in minimsg_network_handler()"); semaphore_V(g_unboundedPortPtrs[destPort]->unbound_port.datagrams_ready); set_interrupt_level(old_level); //restore interrupt level }
void install_disk_handler(interrupt_handler_t disk_handler){ kprintf("Starting disk interrupt.\n"); mini_disk_handler = disk_handler; /* create mutex used to protect disk datastructures */ AbortOnCondition(pthread_mutex_init(&disk_mutex, NULL),"mutex"); }
/* * start polling for network packets. this is separate so that clock interrupts * can be turned on without network interrupts. however, this function requires * that clock_init has been called! */ void start_network_poll(interrupt_handler_t network_handler, int* s) { pthread_t network_thread; sigset_t set; sigset_t old_set; struct sigaction sa; sigemptyset(&set); sigaddset(&set,SIGRTMAX-1); sigaddset(&set,SIGRTMAX-2); sigprocmask(SIG_BLOCK,&set,&old_set); /* create clock and return threads, but discard ids */ AbortOnCondition(pthread_create(&network_thread, NULL, (void*)network_poll, s), "pthread"); sa.sa_handler = (void*)handle_interrupt; sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK; sa.sa_sigaction= (void*)handle_interrupt; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask,SIGRTMAX-2); sigaddset(&sa.sa_mask,SIGRTMAX-1); if (sigaction(SIGRTMAX-2, &sa, NULL) == -1) AbortOnError(0); pthread_sigmask(SIG_SETMASK,&old_set,NULL); }
int transmit_first(int* arg) { char buffer[BUFFER_SIZE]; int length = BUFFER_SIZE; int i; network_address_t addr; miniport_t port; miniport_t dest; miniport_t from; AbortOnCondition(network_translate_hostname(hostname, addr) < 0, "Could not resolve hostname, exiting."); port = miniport_create_unbound(0); dest = miniport_create_bound(addr, 1); for (i=0; i<MAX_COUNT; i++) { printf("Sending packet %d.\n", i+1); sprintf(buffer, "Received packet %d.\n", i+1); length = strlen(buffer) + 1; minimsg_send(port, dest, buffer, length); length = BUFFER_SIZE; minimsg_receive(port, &from, buffer, &length); printf("%s", buffer); miniport_destroy(from); } return 0; }
void minimsg_initialize() { g_boundPortCounter = BOUNDED_PORT_START; //bounded ports range from 32768 - 65535 memset(g_boundedPortAvail, 1, sizeof(g_boundedPortAvail)); //initialize array element to true, every port is avail when we initialize memset(g_unboundedPortPtrs, 0, sizeof(g_unboundedPortPtrs)); //set array of unbounded port pointers to null g_semaLock = semaphore_create(); AbortOnCondition(g_semaLock == NULL, "g_semaLock failed in minimsg_initialize()"); semaphore_initialize(g_semaLock, 1); //init sema to 1 (available). }
int transmit_first(int* arg) { char buffer[MINIMSG_MAX_MSG_SIZE + 10]; int length = 0; int i; network_address_t hostaddr, targetaddr; miniport_t port; miniport_t dest; struct mini_header hdr; AbortOnCondition(network_translate_hostname(hostname, targetaddr) < 0, "Could not resolve hostname, exiting."); port = miniport_create_unbound(0); dest = miniport_create_bound(targetaddr, 1); /* Form correct header */ network_get_my_address(hostaddr); hdr.protocol = PROTOCOL_MINIDATAGRAM; pack_address(hdr.source_address, hostaddr); pack_unsigned_short(hdr.source_port, port->num); pack_address(hdr.destination_address, dest->bound.addr); pack_unsigned_short(hdr.destination_port, dest->bound.remote); /* Send packages with short but correct header and zero data */ printf("Sending packages with short headers.\n"); sprintf(buffer, "Receiving packages with short headers.\n"); length = strlen(buffer) + 1; minimsg_send(port, dest, buffer, length); for (i = 0; i < MINIMSG_HDRSIZE; i++) network_send_pkt(targetaddr, i, (char*)&hdr, 0, buffer); /* Send packages to wrong ports */ printf("Sending packages to wrong destination ports.\n"); sprintf(buffer, "Receiving packages with wrong destination ports.\n"); length = strlen(buffer) + 1; minimsg_send(port, dest, buffer, length); sprintf(buffer, "This message is sent to a wrong port.\n"); length = strlen(buffer) + 1; minimsg_send(port, miniport_create_bound(targetaddr, 0), buffer, length); minimsg_send(port, miniport_create_bound(targetaddr, MAX_UNBOUNDED), buffer, length); minimsg_send(port, miniport_create_bound(targetaddr, MAX_UNBOUNDED + 1), buffer, length); minimsg_send(port, miniport_create_bound(targetaddr, MIN_BOUNDED), buffer, length); minimsg_send(port, miniport_create_bound(targetaddr, MAX_BOUNDED), buffer, length); printf("Send-first finished.\n"); return 0; }
void semaphore_P(semaphore_t *sem) { //Validate input arguments, abort if invalid argument is seen AbortOnCondition(sem == NULL, "Null argument sem in semaphore_P()"); assert(sem->semaWaitQ != NULL); //sanity check interrupt_level_t old_level = set_interrupt_level(DISABLED); //disable interrupts //critical section if (sem->count > 0) sem->count--; else { minithread_t* currThread = minithread_self(); //get the calling thread AbortOnCondition(currThread == NULL, "Failed in minithread_self() method in semaphore_P()"); queue_append(sem->semaWaitQ, currThread); //put thread onto semaphore's wait queue minithread_stop(); //block calling thread, yield processor } set_interrupt_level(old_level); //restore interrupt level }
void semaphore_initialize(semaphore_t *sem, int cnt) { //Validate input arguments, abort if invalid argument is seen AbortOnCondition(sem == NULL || cnt < 0, "Invalid arguments passed to semaphore_initialize()"); interrupt_level_t old_level = set_interrupt_level(DISABLED); //disable interrupts //critical section sem->count = cnt; assert(sem->semaWaitQ != NULL); //sanity checks assert(sem->count == cnt); set_interrupt_level(old_level); //restore interrupts }
void miniport_destroy(miniport_t* miniport) { assert(g_boundPortCounter >= 0); //sanity check to ensure minimsg_initialize() has been called first //validate input AbortOnCondition(miniport == NULL, "Null argument miniport in miniport_destroy()"); //check if unbounded port, if so, we must free our queue and sema if (miniport->port_type == 'u') { assert(miniport->unbound_port.datagrams_ready != NULL && miniport->unbound_port.incoming_data != NULL && miniport->port_number >= UNBOUNDED_PORT_START && miniport->port_number <= UNBOUNDED_PORT_END); //self check //update our global array of unbounded ports first interrupt_level_t old_level = set_interrupt_level(DISABLED); // critical session g_unboundedPortPtrs[miniport->port_number] = NULL; set_interrupt_level(old_level); // end of critical session //free our queue int queueFreeSuccess = queue_free_nodes_and_queue(miniport->unbound_port.incoming_data); AbortOnCondition(queueFreeSuccess == -1, "Queue_free failed in miniport_destroy()"); //free semaphore semaphore_destroy(miniport->unbound_port.datagrams_ready); } else //if bounded port { assert(miniport->port_number >= BOUNDED_PORT_START && miniport->port_number <= BOUNDED_PORT_END); semaphore_P(g_semaLock); //begin critical section g_boundedPortAvail[miniport->port_number - BOUNDED_PORT_START] = true; //set the avail of our bounded port to true semaphore_V(g_semaLock); //end critical section } free(miniport); }
void semaphore_V(semaphore_t *sem) { //Validate input arguments, abort if invalid argument is seen AbortOnCondition(sem == NULL, "Null argument sem in semaphore_V()"); //validate argument assert(sem->semaWaitQ != NULL); interrupt_level_t old_level = set_interrupt_level(DISABLED); //disable interrupts //critical section if (queue_length(sem->semaWaitQ) == 0) sem->count++; else { //if the semaphore wait queue is not empty, then there are threads waiting and the count must be at 0 assert(sem->count == 0); minithread_t* t = NULL; int dequeueSuccess = queue_dequeue(sem->semaWaitQ, (void**) &t); assert(t != NULL); AbortOnCondition(dequeueSuccess != 0, "Failed in queue_dequeue operation in semaphore_V()"); minithread_start(t); } set_interrupt_level(old_level); //restore interrupts }
/* * 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); } }
int network_bcast_pkt(int hdr_len, char* hdr, int data_len, char* data) { int i; int me; AbortOnCondition(!BCAST_ENABLED, "Error: network broadcast not enabled."); if (BCAST_USE_TOPOLOGY_FILE) { me = topology.me; for (i=0; i<topology.entries[me].n_links; i++) { int dest = topology.entries[me].links[i]; if (synthetic_network) { if(genrand() < loss_rate) continue; if(genrand() < duplication_rate) send_pkt(topology.entries[dest].addr, hdr_len, hdr, data_len, data); } if (send_pkt(topology.entries[dest].addr, hdr_len, hdr, data_len, data) != hdr_len + data_len) return -1; } if (BCAST_LOOPBACK) { if (send_pkt(topology.entries[me].addr, hdr_len, hdr, data_len, data) != hdr_len + data_len) return -1; } } else { /* real broadcast */ /* send the packet using the private network broadcast address */ if (send_pkt(broadcast_addr, hdr_len, hdr, data_len, data) != hdr_len + data_len) return -1; } return hdr_len+data_len; }
int minimsg_receive(miniport_t* local_unbound_port, miniport_t** new_local_bound_port, minimsg_t* msg, int *len) { assert(g_boundPortCounter >= 0); //sanity check to ensure minimsg_initialize() has been called first //validate input if (new_local_bound_port == NULL || local_unbound_port == NULL|| msg == NULL || len == NULL || *len < 0) return -1; assert(local_unbound_port->port_type == 'u' && local_unbound_port->unbound_port.datagrams_ready != NULL && local_unbound_port->unbound_port.datagrams_ready != NULL); semaphore_P(local_unbound_port->unbound_port.datagrams_ready); //P the semaphore, if the count is 0 we're blocked until packet arrives //once a packet arrives and we've woken network_interrupt_arg_t* dequeuedPacket = NULL; interrupt_level_t old_level = set_interrupt_level(DISABLED); // critical session (to dequeue the packet queue) assert(queue_length(local_unbound_port->unbound_port.incoming_data) > 0); //sanity check - our queue should have a packet waiting int dequeueSuccess = queue_dequeue(local_unbound_port->unbound_port.incoming_data, (void**)&dequeuedPacket); AbortOnCondition(dequeueSuccess != 0, "Queue_dequeue failed in minimsg_receive()"); set_interrupt_level(old_level); //end of critical session to restore interrupt level //Our packet size should be valid assert(dequeuedPacket->size >= 0); //get our header and message from the dequeued packet assert(dequeuedPacket->size >= sizeof(mini_header_t)); mini_header_t receivedHeader; memcpy(&receivedHeader, dequeuedPacket->buffer, sizeof(mini_header_t)); //set *len to the msg length to be copied: if the length of the message received is >= *len, no change to *len. Otherwise, set *len to the length of our received message if (dequeuedPacket->size - sizeof(mini_header_t) < *len) *len = dequeuedPacket->size - sizeof(mini_header_t); memcpy(msg, dequeuedPacket->buffer + sizeof(mini_header_t), *len); // msg is after header //create our new local bound port pointed back to the sender int sourcePort = (int)unpack_unsigned_short(receivedHeader.source_port); // get source's listening port assert(sourcePort >= UNBOUNDED_PORT_START && sourcePort <= UNBOUNDED_PORT_END); //make sure source port num is valid network_address_t remoteAddr; unpack_address(receivedHeader.source_address, remoteAddr); // get source's network address free(dequeuedPacket); // release the memory allocated to the packet *new_local_bound_port = miniport_create_bound(remoteAddr, sourcePort); // create a bound port if (*new_local_bound_port == NULL) return -1; return *len; //return data payload bytes received not inclusive of header }
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); } }
int transmit(int* arg) { char buffer[BUFFER_SIZE]; int length; network_address_t addr; miniport_t port; miniport_t dest; AbortOnCondition(network_translate_hostname(hostname, addr) < 0, "Could not resolve hostname, exiting."); port = miniport_create_unbound(42); dest = miniport_create_bound(addr, 42); minithread_fork(receive, NULL); while(1){ memset(buffer, 0, BUFFER_SIZE); length = miniterm_read(buffer, BUFFER_SIZE); minimsg_send(port, dest, buffer, length); } return 0; }
/* * Send an interrupt to the system thread: adjust its stack to call * the appropriate interrupt handler with the specified argument. the * "type" argument identifies interrupt-specific processing which must * be done, in particular, what we should do if interrupts are * disabled or the system thread is in a non-preemptable state * (e.g. executing a system library function). clock interrupts are * dropped, network interrupts are deferred. this function replaces * code which used to be common to clock_poll and network_poll. */ void send_interrupt(int type, void* arg) { CONTEXT context; int safe_to_proceed = 0; int drop_interrupt = 0; interrupt_queue_t* interrupt_info = NULL; for (;;) { WaitOnObject(mutex); /* need to protect this code: we only activate the interrupt if interrupts are actually enabled, but we also need to ensure they are not disabled after we test -- so we suspend the system thread first. */ SuspendThread(system_thread); memset(&context, 0, sizeof(CONTEXT)); #ifdef WINCE context.ContextFlags = CONTEXT_FULL; #else context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS; #endif /* Warning: a printf here makes the system lock */ AbortOnError(GetThreadContext(system_thread, &context)); /* find interrupt description in the interrupt queue */ interrupt_info = interrupt_queue; while (interrupt_info!=NULL && interrupt_info->type!=type) interrupt_info = interrupt_info->next; if (interrupt_info == NULL) { /* * we couldn't find the interrupt with type "type" so we crash the * sistem. */ kprintf("INT ERR: An interrupt of the unregistered type %d was received.\n", type); AbortOnCondition(1,"Crashing."); } else { /* * interrupt-type-specific processing: can we interrupt now? If we * ended up interrupting the process at a time when it is in some non-minithread-safe * Windows library, then defer or drop the interrupt. */ switch (interrupt_info->property){ case INTERRUPT_DROP: if (interrupt_level == DISABLED || (EIP < start_address) || (EIP > end_address)) { drop_interrupt = 1; } else { //interrupt_level = DISABLED; safe_to_proceed = 1; } break; case INTERRUPT_DEFER: if (interrupt_level == ENABLED && (EIP >= start_address) && (EIP <= end_address)) { interrupt_level = DISABLED; safe_to_proceed = 1; } break; default: break; } } if (safe_to_proceed == 1) break; else { ResumeThread(system_thread); ReleaseMutex(mutex); if (DEBUG) { switch (interrupt_info->property) { case INTERRUPT_DROP: kprintf("Interrupt of type %d dropped, eip = 0x%x.\n", interrupt_info->type, EIP); break; case INTERRUPT_DEFER: kprintf("Interrupt of type %d deffered, eip = 0x%x.\n", interrupt_info->type, EIP); break; } } } if (drop_interrupt == 1) return; else SwitchToThread(); } /* now fix the system thread's stack so it runs run_user_handler */ { int stack; int oldpc = 0; //if (DEBUG) { //kprintf("Interrupts are enabled, system thread pc = 0x%x\n", EIP); //kprintf("Adjusting system thread context ...\n"); // } /* set the interrupt number */ /* arg->intnumber = ++intnumber; */ oldpc = EIP; stack = ESP; /* Esp == extended stack pointer */ /* safe to do a printf because other thread is stunned in user code */ // if (DEBUG) //kprintf("Suspended system thread, adjusting stack, sp = 0x%x\n", stack); stack -= (sizeof(CONTEXT) + 64); /* 64 is slop */ memcpy((int *) stack, &context, sizeof(CONTEXT)); EIP = (int) ((void *) receive_interrupt); REG1 = stack; /*pointer to context*/ REG2 = (int) type; /*type, second argument */ #ifndef WINCE /* for x86 put arg pointer on the stack since only two parameters can be passed in registers. */ stack-=sizeof(void*); *((int*)stack)=(int) arg; stack-=sizeof(void*); #else /* for ARM put the third argument in R2 */ context.R2 = (int) arg; #endif ESP = stack; AbortOnError(SetThreadContext(system_thread, &context)); AbortOnError(GetThreadContext(system_thread, &context)); ResumeThread(system_thread); } ReleaseMutex(mutex); }