void minithread_yield() { //put current thread at end of runnable semaphore_P(runnable_q_lock); current_thread->priority = 0; current_thread->rem_quanta = 1; if (multilevel_queue_enqueue(runnable_q, current_thread->priority,current_thread) == 0) { runnable_count++; } semaphore_V(runnable_q_lock); //call scheduler here scheduler(); }
/** * Force unmount on all filesystems. This function should be used only * when halting the system. Waits for all VFS operations to complete * but does not wait for all files to be closed. After this function * is called the VFS and the whole operating system can no longer be * used. */ void vfs_deinit(void) { fs_t *fs; int row; semaphore_P(vfs_op_sem); vfs_usable = 0; kprintf("VFS: Entering forceful unmount of all filesystems.\n"); if (vfs_ops > 0) { kprintf("VFS: Delaying force unmount until the pending %d " "operations are done.\n", vfs_ops); semaphore_V(vfs_op_sem); semaphore_P(vfs_unmount_sem); semaphore_P(vfs_op_sem); KERNEL_ASSERT(vfs_ops == 0); kprintf("VFS: Continuing forceful unmount.\n"); } semaphore_P(vfs_table.sem); semaphore_P(openfile_table.sem); for (row = 0; row < CONFIG_MAX_FILESYSTEMS; row++) { fs = vfs_table.filesystems[row].filesystem; if (fs != NULL) { kprintf("VFS: Forcefully unmounting volume [%s]\n", vfs_table.filesystems[row].mountpoint); fs->unmount(fs); vfs_table.filesystems[row].filesystem = NULL; } } semaphore_V(openfile_table.sem); semaphore_V(vfs_table.sem); semaphore_V(vfs_op_sem); }
/* Deletes all the elements in the cleanup_queue and then get the next * RUNNABLE minithread, if it exists. Otherwise, it will continuously poll the * queue and wait until another thread is made RUNNABLE */ int reaper_queue_cleanup(arg_t arg) { //delete all zombie minithreads in cleanup_queue minithread_t* temp; while (1) { semaphore_P(reaper_sema); //waits until something is ready to be deleted if (queue_length(schedule_data->cleanup_queue) > 0) { //double checks size interrupt_level_t old_level = set_interrupt_level(DISABLED); queue_dequeue(schedule_data->cleanup_queue, (void **) &temp); free(temp); set_interrupt_level(old_level); } } // will never return return 0; }
static int employee(int* arg) { phone_t new_phone = NULL; int id = employee_id++; while (1) { /* Check if there is any customer in need of a phone */ semaphore_P(customer_sem); /* Wait if buffer full */ semaphore_P(empty_sem); new_phone = phone_create(); if (NULL != new_phone) { queue_append(phone_queue, new_phone); printf("Employee %d unpacked phone %d\n", id, new_phone->serial_num); } /* Signal a phone is ready */ semaphore_V(full_sem); /* minithread_yield(); */ } return 0; }
/* produce all integers from 2 to max */ int source(int* arg) { channel_t* c = (channel_t *) arg; int i; for (i=2; i<=max; i++) { c->value = i; semaphore_V(c->consume); semaphore_P(c->produce); } c->value = -1; semaphore_V(c->consume); return 0; }
static void minisocket_free (minisocket_t * socket) { network_interrupt_arg_t *packet = NULL; while (queue_dequeue(socket->data, (void **)&packet) != -1) { free(packet); } queue_free(socket->data); socket->data = NULL; semaphore_destroy(socket->data_ready); semaphore_destroy(socket->wait_for_ack); semaphore_destroy(socket->send_receive_mutex); semaphore_P(ports_mutex); ports[socket->local_port] = NULL; semaphore_V(ports_mutex); free(socket); }
// returns new task id uint32_t sched_request_task(task_type type, std::shared_ptr<void> data) { uint32_t task_id; std::unique_ptr<new_task_req> request(new new_task_req); request->tcp = data; request->type = type; request->task_id = task_counter++; task_id = request->task_id; semaphore_P(sched_new_task_lock, 1); new_task_queue.push_back(std::move(request)); semaphore_V(sched_new_task_lock, 1); return task_id; }
/** * Start a new operation on VFS. Operation is defined to be any such * sequence of actions (a VFS function call) that may touch some * filesystem. * * @return VFS_OK if operation can continue, error (negative) if * operation must be cancelled. */ static int vfs_start_op() { int ret = VFS_OK; semaphore_P(vfs_op_sem); if (vfs_usable) { vfs_ops++; } else { ret = VFS_UNUSABLE; } semaphore_V(vfs_op_sem); return ret; }
/* Creates an unbound port for listening. Multiple requests to create the same * unbound port should return the same miniport reference. It is the responsibility * of the programmer to make sure he does not destroy unbound miniports while they * are still in use by other threads -- this would result in undefined behavior. * Unbound ports must range from 0 to 32767. If the programmer specifies a port number * outside this range, it is considered an error. */ miniport_t miniport_create_unbound(int port_number) { miniport_t new_port; if (port_number < 0 || port_number >= BOUND_PORT_START) { // user error return NULL; } if (miniport_array[port_number]) { return miniport_array[port_number]; } semaphore_P(unbound_ports_lock); new_port = (miniport_t)malloc(sizeof(struct miniport)); if (new_port == NULL) { semaphore_V(unbound_ports_lock); return NULL; } new_port->p_type = UNBOUND_PORT; new_port->p_num = port_number; new_port->u.unbound.port_pkt_q = queue_new(); if (!new_port->u.unbound.port_pkt_q) { free(new_port); semaphore_V(unbound_ports_lock); return NULL; } new_port->u.unbound.port_pkt_available_sem = semaphore_create(); if (!new_port->u.unbound.port_pkt_available_sem) { queue_free(new_port->u.unbound.port_pkt_q); free(new_port); semaphore_V(unbound_ports_lock); return NULL; } new_port->u.unbound.q_lock = semaphore_create(); if (!new_port->u.unbound.q_lock) { queue_free(new_port->u.unbound.port_pkt_q); semaphore_destroy(new_port->u.unbound.port_pkt_available_sem); free(new_port); semaphore_V(unbound_ports_lock); return NULL; } semaphore_initialize(new_port->u.unbound.port_pkt_available_sem,0); semaphore_initialize(new_port->u.unbound.q_lock,1); miniport_array[port_number] = new_port; semaphore_V(unbound_ports_lock); return new_port; }
static void ctl_program(int ch, int val) { if(ch >= MAX_TK_MIDI_CHANNELS) return; if (!ctl.trace_playing) return; if (ch < 0 || ch >= MAX_TK_MIDI_CHANNELS) return; if(channel[ch].special_sample) val = channel[ch].special_sample; else val += progbase; semaphore_P(semid); Panel->channel[ch].program = val; Panel->c_flags[ch] |= FLAG_PROG; semaphore_V(semid); }
/** * End a VFS operation. */ static void vfs_end_op() { semaphore_P(vfs_op_sem); vfs_ops--; KERNEL_ASSERT(vfs_ops >= 0); /* Wake up pending unmount if VFS is now idle. */ if (!vfs_usable && (vfs_ops == 0)) semaphore_V(vfs_unmount_sem); if (!vfs_usable && (vfs_ops > 0)) kprintf("VFS: %d operations still pending\n", vfs_ops); semaphore_V(vfs_op_sem); }
int vfs_seek(openfile_t file, int seek_position) { openfile_entry_t *openfile; if (vfs_start_op() != VFS_OK) return VFS_UNUSABLE; KERNEL_ASSERT(seek_position >= 0); semaphore_P(openfile_table.sem); openfile = vfs_verify_open(file); openfile->seek_position = seek_position; semaphore_V(openfile_table.sem); vfs_end_op(); return VFS_OK; }
/* sends a miniroute packet, automatically discovering the path if necessary. * See description in the .h file. */ int miniroute_send_pkt(network_address_t dest_address, int hdr_len, char* hdr, int data_len, char* data) { int total_len = hdr_len + data_len; int sent_len = 0; struct routing_header routing_hdr; char *total_data = malloc(total_len); miniroute_path_t path = NULL; /* Find route if it is not in cache */ semaphore_P(discovery_mutex); miniroute_cache_get_by_addr(route_cache, dest_address, (void**)&path); if (NULL == path || path->exp_time < ticks) { #if MINIROUTE_CACHE_DEBUG == 1 printf("Address not found, discovering path.\n"); #endif path = miniroute_discover_path(dest_address); } semaphore_V(discovery_mutex); if (NULL != path && NULL != (total_data = malloc(total_len))) { /* Pack data and miniroute header */ memcpy(total_data, hdr, hdr_len); memcpy(total_data + hdr_len, data, data_len); miniroute_pack_data_hdr(&routing_hdr, path); sent_len = network_send_pkt(path->hop[1], MINIROUTE_HDRSIZE, (char*)&routing_hdr, total_len, total_data); } #if MINIROUTE_DEBUG == 1 printf("Network packet sent.\n"); #endif #if MINIROUTE_CACHE_DEBUG == 1 printf("Sending data with header: \n"); miniroute_print_hdr(&routing_hdr); #endif if (sent_len < hdr_len) return -1; else return sent_len - hdr_len; }
/* Creates a bound port for use in sending packets. The two parameters, addr and * remote_unbound_port_number together specify the remote's listening endpoint. * This function should assign bound port numbers incrementally between the range * 32768 to 65535. Port numbers should not be reused even if they have been destroyed, * unless an overflow occurs (ie. going over the 65535 limit) in which case you should * wrap around to 32768 again, incrementally assigning port numbers that are not * currently in use. */ miniport_t miniport_create_bound(network_address_t addr, int remote_unbound_port_number) { int num; semaphore_P(port_mutex); num = miniport_get_boundedport_num(); if (num < MIN_BOUNDED || num > MAX_BOUNDED) { semaphore_V(port_mutex); return NULL; } if ((port[num] = malloc(sizeof(struct miniport))) != NULL) { port[num]->type = BOUNDED; port[num]->num = num; network_address_copy(addr, port[num]->bound.addr); port[num]->bound.remote = remote_unbound_port_number; } semaphore_V(port_mutex); return port[num]; }
std::string sched_get_running_tasks() { std::stringstream ss; semaphore_P(sched_lock, 1); for (int i = 0; i < CORE_COUNT; i++) { if (sched_active_task(i)) { ss << i << "| "; ss << running_tasks[i]->task_id << ' '; ss << task_state_names[running_tasks[i]->state] << ' '; ss << task_type_names[running_tasks[i]->type] << '\n'; } } semaphore_V(sched_lock, 1); return ss.str(); }
void minisocket_destroy(minisocket_t sock, minisocket_error* error){ network_interrupt_arg_t* pkt; semaphore_P(server_lock); sock_array[sock->src_port] = NULL; semaphore_V(server_lock); *error = SOCKET_NOERROR; //free all queued packets. interrupts not disabled //because socket in array set to null, network //handler cannot access queue while (queue_dequeue(sock->pkt_q,(void**)&pkt) != -1){ free(pkt); } queue_free(sock->pkt_q); semaphore_destroy(sock->pkt_ready_sem); semaphore_destroy(sock->ack_ready_sem); semaphore_destroy(sock->sock_lock); free(sock); }
std::string sched_get_cores_info() { std::stringstream ss; semaphore_P(sched_lock, 1); for (int i = 0; i < CORE_COUNT; i++) { if (sched_active_task(i)) { ss << "core " << i << " occupied" << '\n'; } else { ss << "core " << i << " free" << '\n'; } } semaphore_V(sched_lock, 1); return ss.str(); }
int main() { struct exchange { char buf[BUFSIZ+80]; int seq; }shm; int shmid; unsigned char *retval; int producer, consumer, i; char readbuf[BUFSIZ]; //创建信号量consumer consumer = open_semaphore_set(ftok("consumer", 0), 1); //初始化信号量consumer的值为1 init_a_semaphore(consumer, 0, 1); //创建信号量producer producer = open_semaphore_set(ftok("producer", 0), 1); //初始化信号量producer的值为1 init_a_semaphore(producer, 0, 1); //创建共享存储区用于存放生产者产生的数据 shmid = shmget(ftok("share", 0),sizeof(struct exchange), 0666|IPC_CREAT); retval = shmat(shmid, (unsigned char *)0, 0); //生产者与消费者同步 for (i = 0; ; i++) { printf("enter some text:"); fgets(readbuf, BUFSIZ, stdin); semaphore_P(consumer); sprintf(retval, "messge %2d form producer %d is \" %s \" ", i, getpid(), readbuf); semaphore_V(producer); if (strncmp(readbuf, "end", 3) == 0) break; } exit(0); return 0; }
/* * Destroys a miniport and frees up its resources. If the miniport was in use at * the time it was destroyed, subsequent behavior is undefined. */ void miniport_destroy(miniport_t miniport) { semaphore_P(port_mutex); if (NULL == miniport) { semaphore_V(port_mutex); return; } if (UNBOUNDED == miniport->type) { queue_free(miniport->unbound.data); semaphore_destroy(miniport->unbound.ready); } if (BOUNDED == miniport->type) { --bound_count; } port[miniport->num] = NULL; free(miniport); semaphore_V(port_mutex); }
int vfs_mount(fs_t *fs, char *name) { int i; int row; KERNEL_ASSERT(name != NULL && name[0] != '\0'); if (vfs_start_op() != VFS_OK) return VFS_UNUSABLE; semaphore_P(vfs_table.sem); for (i = 0; i < CONFIG_MAX_FILESYSTEMS; i++) { if (vfs_table.filesystems[i].filesystem == NULL) break; } row = i; if(row >= CONFIG_MAX_FILESYSTEMS) { semaphore_V(vfs_table.sem); kprintf("VFS: Warning, maximum mount count exceeded, mount failed.\n"); vfs_end_op(); return VFS_LIMIT; } for (i = 0; i < CONFIG_MAX_FILESYSTEMS; i++) { if(stringcmp(vfs_table.filesystems[i].mountpoint, name) == 0) { semaphore_V(vfs_table.sem); kprintf("VFS: Warning, attempt to mount 2 filesystems " "with same name\n"); vfs_end_op(); return VFS_ERROR; } } stringcopy(vfs_table.filesystems[row].mountpoint, name, VFS_NAME_LENGTH); vfs_table.filesystems[row].filesystem = fs; semaphore_V(vfs_table.sem); vfs_end_op(); return VFS_OK; }
miniport_t* miniport_create_bound(network_address_t addr, int remote_unbound_port_number) { assert(g_boundPortCounter >= 0); //sanity check to ensure minimsg_initialize() has been called first //validate input, unbound port number should be between 0 - 32767 if (addr == NULL || remote_unbound_port_number < UNBOUNDED_PORT_START || remote_unbound_port_number > UNBOUNDED_PORT_END) return NULL; miniport_t* b_miniport = malloc(sizeof(miniport_t)); if (b_miniport == NULL) return NULL; //malloc errored b_miniport->port_type = 'b'; //set miniport type to bounded b_miniport->bound_port.remote_unbound_port = remote_unbound_port_number; memcpy(b_miniport->bound_port.remote_addr, addr, sizeof(network_address_t)); semaphore_P(g_semaLock); //critical section to access global variables g_boundPortCounter & g_boundedPortAvail if (g_boundPortCounter > BOUNDED_PORT_END) //if we've reached the end of our port space, we need to search for an available port number { int k = 0; while (k <= BOUNDED_PORT_END - BOUNDED_PORT_START && g_boundedPortAvail[k] == false) k++; // find the first element equaling true if (k > BOUNDED_PORT_END - BOUNDED_PORT_START) { //if no port is available free(b_miniport); // free the newly created bound port b_miniport = NULL; // will return NULL later } else { // found an available port b_miniport->port_number = k + BOUNDED_PORT_START; // set our miniport num to the available port num g_boundedPortAvail[k] = false; //set the port to be used } } else //otherwise, set our port number to g_boundPortCounter { b_miniport->port_number = g_boundPortCounter; g_boundedPortAvail[g_boundPortCounter - BOUNDED_PORT_START] = false; //set the avail of that port to false g_boundPortCounter++; //increment counter } semaphore_V(g_semaLock); //end of critical section return b_miniport; }
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 }
static int customer(int* arg) { phone_t new_phone = NULL; int id = customer_id++; printf("Customer %d is waiting for a phone\n", id); /* Signal employee there is a customer */ semaphore_V(customer_sem); /* Wait if no unpacked phone */ semaphore_P(full_sem); queue_dequeue(phone_queue, (void**)&new_phone); printf("Customer %d got phone %d\n", id, new_phone->serial_num); free(new_phone); /* Signal a buffer slot is open */ semaphore_V(empty_sem); return 0; }
/* Destroys a miniport and frees up its resources. If the miniport was in use at * the time it was destroyed, subsequent behavior is undefined. */ void miniport_destroy(miniport_t miniport) { semaphore_P(msgmutex); // Check for valid argument if (miniport == NULL) { fprintf(stderr, "ERROR: miniport_destroy() passed a NULL miniport argument\n"); semaphore_V(msgmutex); return; } ports[miniport->port_num] = NULL; // Clear the miniport from the ports array if (miniport->port_type == BOUND) { semaphore_V(bound_ports_free); // Increment the bound port counting semaphore } //When to destroy? bounded->thread that used it terminates; unbounded->when last packet waits right there? free(miniport); semaphore_V(msgmutex); }
minithread_t minithread_create(proc_t proc, arg_t arg) { minithread_t new_thread = (minithread_t)malloc(sizeof(minithread)); if (new_thread == NULL){ return NULL; } semaphore_P(id_lock); new_thread->id = current_id++; semaphore_V(id_lock); new_thread->priority = 0; new_thread->rem_quanta = 1; new_thread->stackbase = NULL; new_thread->stacktop = NULL; new_thread->status = RUNNABLE; minithread_allocate_stack(&(new_thread->stackbase), &(new_thread->stacktop) ); minithread_initialize_stack(&(new_thread->stacktop), proc, arg, (proc_t)minithread_exit, NULL); return new_thread; }
void minisocket_close(minisocket_t *socket) { if (socket) { if (socket->socket_state == CLOSING) { socket->socket_state = WAITING_SYN; return; } if (socket->socket_state == CLOSED) { minisocket_free(socket); return; } minisocket_error s_error; int wait_val = 100; while (wait_val <= 12800) { send_control_message(MSG_FIN, socket->remote_port, socket->remote_addr, socket->local_port, socket->seq_number, socket->ack_number, &s_error); socket->seq_number += 1; if (s_error == SOCKET_OUTOFMEMORY) { return; } alarm_id a = register_alarm(wait_val, (alarm_handler_t) semaphore_V, socket->wait_for_ack); semaphore_P(socket->wait_for_ack); interrupt_level_t old_level = set_interrupt_level(DISABLED); if (socket->ack_flag == 0) { wait_val *= 2; socket->seq_number--; set_interrupt_level(old_level); continue; } else if (socket->ack_flag == 1) { deregister_alarm(a); minisocket_free(socket); set_interrupt_level(old_level); return; } } } semaphore_V(socket->send_receive_mutex); }
int consumer(int* arg) { int n, i; int out = 0; while (out < *arg) { n = genintrand(BUFFER_SIZE); n = (n <= *arg - out) ? n : *arg - out; printf("Consumer wants to get %d items out of buffer ...\n", n); for (i=0; i<n; i++) { semaphore_P(empty); out = buffer[tail]; printf("Consumer is taking %d out of buffer.\n", out); tail = (tail + 1) % BUFFER_SIZE; size--; semaphore_V(full); } } return 0; }
/*ARGSUSED*/ static int TraceReset(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) { int i; semaphore_P(semid); for (i = 0; i < 32; i++) { trace_volume(i, 0); trace_panning(i, -1); trace_prog_init(i); trace_prog(i, 0); trace_sustain(i, 0); Panel->ctotal[i] = 0; Panel->cvel[i] = 0; Panel->v_flags[i] = 0; Panel->c_flags[i] = 0; } semaphore_V(semid); Panel->wait_reset = 0; return TCL_OK; }
int sink(int* arg) { channel_t* p = (channel_t *) malloc(sizeof(channel_t)); int value; p->produce = semaphore_create(); semaphore_initialize(p->produce, 0); p->consume = semaphore_create(); semaphore_initialize(p->consume, 0); minithread_fork(source, (int *) p); for (;;) { filter_t* f; semaphore_P(p->consume); value = p->value; semaphore_V(p->produce); if (value == -1) break; printf("%d is prime.\n", value); f = (filter_t *) malloc(sizeof(filter_t)); f->left = p; f->prime = value; p = (channel_t *) malloc(sizeof(channel_t)); p->produce = semaphore_create(); semaphore_initialize(p->produce, 0); p->consume = semaphore_create(); semaphore_initialize(p->consume, 0); f->right = p; minithread_fork(filter, (int *) f); } return 0; }
int vfs_close(openfile_t file) { openfile_entry_t *openfile; fs_t *fs; int ret; if (vfs_start_op() != VFS_OK) return VFS_UNUSABLE; semaphore_P(openfile_table.sem); openfile = vfs_verify_open(file); fs = openfile->filesystem; ret = fs->close(fs, openfile->fileid); openfile->filesystem = NULL; semaphore_V(openfile_table.sem); vfs_end_op(); return ret; }