TASKQ *task_freeq (TASKQ *q) { TASK *t; task_stop (q); wait_mutex (q); debug ("freeing queue\n"); while ((t = q->queue) != NULL) { q->queue = t->next; free (t); } debug ("freeing pool\n"); while ((t = q->pool) != NULL) { q->pool = t->next; free (t); } debug ("closing event and critical section\n"); end_mutex (q); destroy_mutex (q); destroy_ready (q); free (q); return (NULL); }
void signal(int threadid, int *msg, int senderid, int signal_type) { int i = 0; wait_mutex(&working_threads[threadid].waiting_for_signal_mutex); if(working_threads[threadid].signal_senderid != senderid || working_threads[threadid].waiting_for_signal == 0 || working_threads[threadid].expected_signal_type != signal_type) { // unexpected signal, discard it leave_mutex(&working_threads[threadid].waiting_for_signal_mutex); return; } // send signal working_threads[threadid].expected_signal_type = OFS_THREADSIGNAL_NOSIGNAL; working_threads[threadid].signal_type = signal_type; working_threads[threadid].signal_senderid = senderid; if(msg != NULL) { working_threads[threadid].signal_msg[0] = *msg++; working_threads[threadid].signal_msg[1] = *(msg++); working_threads[threadid].signal_msg[2] = *(msg++); working_threads[threadid].signal_msg[3] = *(msg); } leave_mutex(&working_threads[threadid].waiting_for_signal_mutex); working_threads[threadid].waiting_for_signal = 0; }
// this function should be invoked before sending msgs void set_wait_for_signal(int threadid, int signal_type, int senderid) { wait_mutex(&working_threads[threadid].waiting_for_signal_mutex); working_threads[threadid].expected_signal_type = signal_type; working_threads[threadid].signal_senderid = senderid; working_threads[threadid].waiting_for_signal = 1; leave_mutex(&working_threads[threadid].waiting_for_signal_mutex); }
int check_idle() { int ret; wait_mutex(&idle_threads_mutex); ret = idle_threads > 0; leave_mutex(&idle_threads_mutex); return ret; }
void free(void *ptr) { # ifdef SAFE wait_mutex(&malloc_mutex); # endif _mem_free(ptr); # ifdef SAFE leave_mutex(&malloc_mutex); # endif }
/* * Stop and wait for all threads to exit (assume we are one of them). * If stop is already set, return non-zero. */ int task_stop (TASKQ *q) { wait_mutex (q); if (q->stop) { end_mutex (q); return (-1); } q->stop = 1; debug ("waiting on tasks to exit...\n"); while (q->waiting || q->running) { set_ready (q); end_mutex (q); sleep (100); wait_mutex (q); } end_mutex (q); debug ("stop completed\n"); return (0); }
void *calloc(size_t nelem, size_t elsize) { void *ptr = NULL; # ifdef SAFE wait_mutex(&malloc_mutex); # endif ptr = _mem_alloc(nelem * elsize, 1); # ifdef SAFE leave_mutex(&malloc_mutex); # endif return ptr; }
void *malloc(size_t size) { void *ptr = NULL; # ifdef SAFE wait_mutex(&malloc_mutex); # endif ptr = _mem_alloc(size, 0); # ifdef SAFE leave_mutex(&malloc_mutex); # endif return ptr; }
/* * reset active tasks */ int task_reset (TASKQ *q) { TASK *t; wait_mutex (q); while ((t = q->queue) != NULL) { q->queue = t->next; t->next = q->pool; q->pool = t; } end_mutex (q); return (0); }
/* * start as many threads as might be needed for the current queue */ int task_start (TASKQ *q) { int num_tasks = 0; TASK *t; wait_mutex (q); q->stop = 0; for (t = q->queue; t != NULL; t = t->next) num_tasks++; num_tasks -= q->waiting; set_ready (q); while ((num_tasks-- > 0) && (q->running < q->maxthreads)) { debug ("starting new task\n"); q->running++; t_start (task_run, q); } end_mutex (q); return (0); }
struct stdfss_res *mkdevice(int wpid, struct working_thread *thread, struct stdfss_mkdevice *mkdevice_cmd) { struct stdfss_res *ret = NULL; struct smount_info *minf = NULL; struct sdevice_info *opening_dinf = NULL; char *str = NULL, *strmatched = NULL; int parse_ret, dir_exists; struct gc_node *dir_base_node = NULL, *device_base_node = NULL; unsigned int *block = NULL; unsigned int nodeid; // get device file name from smo str = get_string(mkdevice_cmd->path_smo); ret = check_path(str, thread->command.command); if(ret != NULL) return ret; char *devstr = get_string(mkdevice_cmd->service_name); ret = check_path(devstr, thread->command.command); if(ret != NULL) { free(str); return ret; } // check path is ok if(str[len(str)] == '/') { free(str); free(devstr); return build_response_msg(thread->command.command, STDFSSERR_INVALID_COMMAND_PARAMS); } // get mount info wait_mutex(&mounted_mutex); minf = (struct smount_info *)lpt_getvalue_parcial_matchE(mounted, str, &strmatched); leave_mutex(&mounted_mutex); if(minf == NULL) { free(str); free(devstr); return build_response_msg(mkdevice_cmd->command, STDFSSERR_DEVICE_NOT_MOUNTED); } // check file does not exist parse_ret = parse_directory(TRUE, &dir_base_node, OFS_NODELOCK_EXCLUSIVE | OFS_NODELOCK_BLOCKING, thread->command.command, thread, wpid, minf, str, len(strmatched), NULL, &nodeid, NULL, &dir_exists, &ret); if(ret != NULL) free(ret); ret = NULL; if(parse_ret) { // file exists if(thread->lastdir_parsed_node != NULL) { nfree(minf->dinf, thread->lastdir_parsed_node); thread->lastdir_parsed_node = NULL; } free(strmatched); free(str); free(devstr); unlock_node(wpid, FALSE, OFS_LOCKSTATUS_OK); nfree(minf->dinf, dir_base_node); return build_response_msg(thread->command.command, STDFSSERR_FILE_EXISTS); } if(!dir_exists) { // worng path if(thread->lastdir_parsed_node != NULL) { nfree(minf->dinf, thread->lastdir_parsed_node); thread->lastdir_parsed_node = NULL; } free(strmatched); free(str); free(devstr); return build_response_msg(thread->command.command, STDFSSERR_FILE_DOESNOTEXIST); } dir_base_node = nref(minf->dinf, thread->lastdir_parsed_node->nodeid); free(strmatched); // Create device file if(!create_file(dir_base_node, str, last_index_of(str, '/') + 1, OFS_DEVICE_FILE, TRUE, minf, wpid, thread->command.command, &nodeid, &device_base_node, OFS_NOFLAGS , &ret)) { nfree(minf->dinf, thread->lastdir_parsed_node); nfree(minf->dinf, dir_base_node); thread->lastdir_parsed_node = NULL; free(str); free(devstr); return ret; } nfree(minf->dinf, thread->lastdir_parsed_node); nfree(minf->dinf, dir_base_node); thread->lastdir_parsed_node = NULL; // get a free block block = get_free_blocks(1, TRUE, minf, thread->command.command, wpid, &ret); if(ret != NULL) { free(str); free(devstr); unlock_node(wpid, FALSE, OFS_LOCKSTATUS_OK); nfree(minf->dinf, device_base_node); return ret; } free(str); clear_dir_buffer(thread->directory_buffer.buffer); // write buffer /* int LOGIC DEVICE ID: internal ID on the service (4 BYTES) int service name size; (4 BYTES) char SERVICE NAME[]: name of the device driver (zero terminated devstring) */ *((unsigned int *)thread->directory_buffer.buffer) = (unsigned int)mkdevice_cmd->logic_deviceid; *((unsigned int *)(thread->directory_buffer.buffer + 4)) = len(devstr); mem_copy((unsigned char *)devstr, ((unsigned char *)thread->directory_buffer.buffer + 8), len(devstr) + 1); free(devstr); write_buffer((char *)thread->directory_buffer.buffer, OFS_DIR_BUFFERSIZE, *block, thread->command.command, wpid, minf, &ret); if(ret != NULL) { free_block(TRUE, TRUE, *block, minf, thread->command.command, wpid, &ret); free(block); unlock_node(wpid, FALSE, OFS_LOCKSTATUS_OK); nfree(minf->dinf, device_base_node); return ret; } // update node device_base_node->n.file_size = 8 + len(devstr) + 1; device_base_node->n.blocks[0] = *block; if(!write_node(device_base_node, minf, wpid, thread->command.command, &ret) || ret != NULL) { free_block(TRUE, TRUE, *block, minf, thread->command.command, wpid, &ret); free(block); unlock_node(wpid, FALSE, OFS_LOCKSTATUS_OK); nfree(minf->dinf, device_base_node); return ret; } nfree(minf->dinf, device_base_node); // unlock device node unlock_node(wpid, FALSE, OFS_LOCKSTATUS_OK); return build_response_msg(thread->command.command, STDFSSERR_OK); }
void decrement_idle() { wait_mutex(&idle_threads_mutex); idle_threads--; leave_mutex(&idle_threads_mutex); }
void signal_idle() { wait_mutex(&idle_threads_mutex); idle_threads++; leave_mutex(&idle_threads_mutex); }
struct stdfss_res *mkdir(int wpid, struct working_thread *thread, struct stdfss_mkdir *mkdir_cmd) { struct stdfss_res *ret = NULL; struct smount_info *minf = NULL; struct sdevice_info *opening_dinf = NULL; char *str = NULL, *old_str = NULL, *strmatched = NULL; int parse_ret, dir_exists; struct gc_node *dir_base_node = NULL, *new_dir_base_node = NULL; unsigned int nodeid; // get dir name from smo str = get_string(mkdir_cmd->dir_path); ret = check_path(str, thread->command.command); if(ret != NULL) return ret; // get mount info wait_mutex(&mounted_mutex); minf = (struct smount_info *)lpt_getvalue_parcial_matchE(mounted, str, &strmatched); leave_mutex(&mounted_mutex); if(minf == NULL) { ret = build_response_msg(mkdir_cmd->command, STDFSSERR_DEVICE_NOT_MOUNTED); free(str); return ret; } // remove trailing '/' if(str[len(str)] == '/') { old_str = str; str = substring(str, 0, len(str) - 1); free(old_str); } // check file does not exist parse_ret = parse_directory(TRUE, &dir_base_node, OFS_NODELOCK_EXCLUSIVE | OFS_NODELOCK_BLOCKING, thread->command.command, thread, wpid, minf, str, len(strmatched), NULL, &nodeid, NULL, &dir_exists, &ret); if(ret != NULL) free(ret); ret = NULL; free(strmatched); if(parse_ret) { // file exists if(thread->lastdir_parsed_node != NULL) { nfree(minf->dinf, thread->lastdir_parsed_node); thread->lastdir_parsed_node = NULL; } free(str); unlock_node(wpid, FALSE, OFS_LOCKSTATUS_OK); nfree(minf->dinf, dir_base_node); return build_response_msg(thread->command.command, STDFSSERR_FILE_EXISTS); } if(!dir_exists) { // worng path if(thread->lastdir_parsed_node != NULL) { nfree(minf->dinf, thread->lastdir_parsed_node); thread->lastdir_parsed_node = NULL; } free(str); return build_response_msg(thread->command.command, STDFSSERR_FILE_DOESNOTEXIST); } dir_base_node = thread->lastdir_parsed_node; // Create directory file if(!create_file(dir_base_node, str, last_index_of(str, '/') + 1, OFS_DIRECTORY_FILE, TRUE, minf, wpid, thread->command.command, &nodeid, &new_dir_base_node , OFS_NOFLAGS, &ret)) { if(thread->lastdir_parsed_node != NULL) { nfree(minf->dinf, thread->lastdir_parsed_node); thread->lastdir_parsed_node = NULL; } free(str); return ret; } nfree(minf->dinf, thread->lastdir_parsed_node); thread->lastdir_parsed_node = NULL; nfree(minf->dinf, new_dir_base_node); free(str); // unlock the dir node unlock_node(wpid, FALSE, OFS_LOCKSTATUS_OK); return build_response_msg(thread->command.command, STDFSSERR_OK); }