static ChannelServer * channel_server_create(PeerServer * ps, noPollCtx * np_ctx, noPollConn * np_listener, int is_ssl) { ServerNP * si = (ServerNP *)loc_alloc_zero(sizeof *si); /* TODO: need to investigate usage of sizeof(sockaddr_storage) for address buffer size */ si->serv.close = server_close; si->sock = nopoll_conn_socket(np_listener); si->serv.ps = ps; if (server_list.next == NULL) { list_init(&server_list); post_event_with_delay(refresh_all_peer_servers, NULL, PEER_DATA_REFRESH_PERIOD * 1000000); } list_add_last(&si->serv.servlink, &channel_server_root); shutdown_set_normal(&channel_shutdown); list_add_last(&si->servlink, &server_list); refresh_peer_server(si->sock, ps); si->accreq.done = np_server_accept_done; si->accreq.u.user.data = si; si->accreq.u.user.func = np_wt_accept; si->accreq.client_data = si; si->accreq.type = AsyncReqUser; si->np_listener = np_listener; si->np_ctx = np_ctx; si->is_ssl = is_ssl; async_req_post(&si->accreq); return &si->serv; }
void * tmp_alloc(size_t size) { void * p; LINK * l; assert(is_dispatch_thread()); if (!tmp_gc_posted) { post_event(gc_event, NULL); tmp_gc_posted = 1; } #if ENABLE_FastMemAlloc if (tmp_pool_pos + size + ALIGNMENT + sizeof(size_t *) > tmp_pool_max) { if (tmp_pool != NULL) { l = (LINK *)tmp_pool; list_add_last(l, &tmp_alloc_list); tmp_alloc_size += tmp_pool_pos; } tmp_pool_max = POOL_SIZE / 0x10 + size; tmp_pool = (char *)loc_alloc(tmp_pool_max); tmp_pool_pos = sizeof(LINK); } tmp_pool_pos += sizeof(size_t *); tmp_pool_pos = (tmp_pool_pos + ALIGNMENT - 1) & ~(ALIGNMENT - 1); p = tmp_pool + tmp_pool_pos; *((size_t *)p - 1) = size; tmp_pool_pos += size; return p; #else l = (LINK *)loc_alloc(sizeof(LINK) + size); list_add_last(l, &tmp_alloc_list); tmp_alloc_size += size + ALIGNMENT + sizeof(size_t *); p = l + 1; return p; #endif }
void cache_wait(AbstractCache * cache) { #else void cache_wait_dbg(const char * file, int line, AbstractCache * cache) { #endif assert(is_dispatch_thread()); assert(client_exited == 0); if (current_client.client != NULL && cache_miss_cnt == 0) { if (cache->wait_list_cnt >= cache->wait_list_max) { cache->wait_list_max += 8; cache->wait_list_buf = (WaitingCacheClient *)loc_realloc(cache->wait_list_buf, cache->wait_list_max * sizeof(WaitingCacheClient)); } if (current_client.args != NULL && !current_client.args_copy) { void * mem = loc_alloc(current_client.args_size); memcpy(mem, current_client.args, current_client.args_size); current_client.args = mem; current_client.args_copy = 1; } #ifndef NDEBUG current_client.file = file; current_client.line = line; #endif if (cache->wait_list_cnt == 0) list_add_last(&cache->link, &cache_list); cache->wait_list_buf[cache->wait_list_cnt++] = current_client; channel_lock(current_client.channel); } #ifndef NDEBUG else if (current_client.client == NULL) { trace(LOG_ALWAYS, "cache_wait(): illegal cache access at %s:%d", file, line); } #endif cache_miss_cnt++; exception(ERR_CACHE_MISS); }
int virtual_stream_eos(Channel * c, char * token, char * id) { size_t done = 0; WriteRequest * r = NULL; int err = 0; StreamClient * client = find_client(id, c); if (client == NULL) err = errno; if (!err && (client->stream->access & VS_ENABLE_REMOTE_WRITE) == 0) err = ERR_UNSUPPORTED; if (!err && !list_is_empty(&client->write_requests)) r = (WriteRequest *)loc_alloc_zero(sizeof(WriteRequest)); if (!err && r == NULL && virtual_stream_add_data(client->stream, NULL, 0, &done, 1) < 0) err = errno; if (r != NULL) { list_init(&r->link_client); r->client = client; r->eos = 1; strlcpy(r->token, token, sizeof(r->token)); list_add_last(&r->link_client, &client->write_requests); } else if (err == 0) { write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, err); write_stream(&c->out, MARKER_EOM); } if (err != 0) errno = err; return err == 0 ? 0 : -1; }
int virtual_stream_read(Channel * c, char * token, char * id, size_t size) { int err = 0; StreamClient * client = find_client(id, c); if (client == NULL) err = errno; if (!err && (client->stream->access & VS_ENABLE_REMOTE_READ) == 0) err = ERR_UNSUPPORTED; if (err == 0) { VirtualStream * stream = client->stream; if (client->pos == stream->pos && !stream->eos_inp) { ReadRequest * r = (ReadRequest *)loc_alloc_zero(sizeof(ReadRequest)); list_init(&r->link_client); r->client = client; r->size = size; strlcpy(r->token, token, sizeof(r->token)); list_add_last(&r->link_client, &client->read_requests); } else { assert(list_is_empty(&client->read_requests)); assert(client->channel == c); send_read_reply(client, token, size); advance_stream_buffer(stream); } } else errno = err; return err == 0 ? 0 : -1; }
/** add item to any position */ void list_add (linked_list* _this, void* item, int position) { // index out of list size if (position > _this->size) { return; } // add to head if (position == 0) { list_add_first(_this, item); } else if (position == _this->size) { // add to tail list_add_last(_this, item); } else { // insert between head and tail node* n = _this->head; int i = 0; // loop until the position while (i < position) { n = n->next; i++; } // insert new node to position node* newNode = list_create_node(item); list_insert_before(_this, n, newNode); _this->size++; } }
static void command_eos(char * token, Channel * c) { char id[256]; StreamClient * client = NULL; size_t done = 0; WriteRequest * r = NULL; int err = 0; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); client = find_client(id, c); if (client == NULL) err = errno; if (!err && (client->stream->access & VS_ENABLE_REMOTE_WRITE) == 0) err = ERR_UNSUPPORTED; if (!err && !list_is_empty(&client->write_requests)) r = loc_alloc_zero(sizeof(WriteRequest)); if (!err && r == NULL && virtual_stream_add_data(client->stream, NULL, 0, &done, 1) < 0) err = errno; if (r != NULL) { list_init(&r->link_client); r->client = client; r->eos = 1; strncpy(r->token, token, sizeof(r->token) - 1); list_add_last(&r->link_client, &client->write_requests); } else { write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, err); write_stream(&c->out, MARKER_EOM); } }
void * tmp_realloc(void * ptr, size_t size) { if (ptr == NULL) return tmp_alloc(size); assert(is_dispatch_thread()); assert(tmp_gc_posted); #if ENABLE_FastMemAlloc { void * p; size_t m = *((size_t *)ptr - 1); if (m >= size) return ptr; if ((char *)ptr >= tmp_pool && (char *)ptr <= tmp_pool + tmp_pool_max) { size_t pos = tmp_pool_pos - m; if (ptr == tmp_pool + pos && pos + size <= tmp_pool_max) { tmp_pool_pos = pos + size; *((size_t *)ptr - 1) = size; return ptr; } } p = tmp_alloc(size); if (m > size) m = size; return memcpy(p, ptr, m); } #else { LINK * l = (LINK *)ptr - 1; list_remove(l); l = (LINK *)loc_realloc(l, sizeof(LINK) + size); list_add_last(l, &tmp_alloc_list); return l + 1; } #endif }
static IORequest * create_io_request(char * token, OpenFileInfo * handle, int type) { IORequest * req = loc_alloc_zero(sizeof(IORequest)); req->req = type; req->handle = handle; req->info.done = done_io_request; req->info.client_data = req; strncpy(req->token, token, sizeof(req->token) - 1); list_add_last(&req->link_reqs, &handle->link_reqs); return req; }
static void run_cache_client(int retry) { Trap trap; unsigned i; unsigned id = current_client.id; void * args_copy = NULL; assert(id != 0); current_cache = NULL; cache_miss_cnt = 0; def_channel = NULL; if (current_client.args_copy) args_copy = current_client.args; for (i = 0; i < listeners_cnt; i++) listeners[i](retry ? CTLE_RETRY : CTLE_START); if (set_trap(&trap)) { current_client.client(current_client.args); clear_trap(&trap); assert(current_client.id == 0); assert(cache_miss_cnt == 0); } else if (id != current_client.id) { trace(LOG_ALWAYS, "Unhandled exception in data cache client: %s", errno_to_str(trap.error)); assert(current_client.id == 0); assert(cache_miss_cnt == 0); } else { if (get_error_code(trap.error) != ERR_CACHE_MISS || cache_miss_cnt == 0 || current_cache == NULL) { trace(LOG_ALWAYS, "Unhandled exception in data cache client: %s", errno_to_str(trap.error)); for (i = 0; i < listeners_cnt; i++) listeners[i](CTLE_COMMIT); } else { AbstractCache * cache = current_cache; if (cache->wait_list_cnt >= cache->wait_list_max) { cache->wait_list_max += 8; cache->wait_list_buf = (WaitingCacheClient *)loc_realloc(cache->wait_list_buf, cache->wait_list_max * sizeof(WaitingCacheClient)); } if (current_client.args != NULL && !current_client.args_copy) { void * mem = loc_alloc(current_client.args_size); memcpy(mem, current_client.args, current_client.args_size); current_client.args = mem; current_client.args_copy = 1; } if (cache->wait_list_cnt == 0) list_add_last(&cache->link, &cache_list); if (current_client.channel != NULL) channel_lock_with_msg(current_client.channel, channel_lock_msg); cache->wait_list_buf[cache->wait_list_cnt++] = current_client; for (i = 0; i < listeners_cnt; i++) listeners[i](CTLE_ABORT); args_copy = NULL; } memset(¤t_client, 0, sizeof(current_client)); current_cache = NULL; cache_miss_cnt = 0; def_channel = NULL; } if (args_copy != NULL) loc_free(args_copy); }
static void command_read(char * token, Channel * c) { char id[256]; size_t size = 0; StreamClient * client = NULL; int err = 0; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); size = json_read_ulong(&c->inp); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); client = find_client(id, c); if (client == NULL) err = errno; if (!err && (client->stream->access & VS_ENABLE_REMOTE_READ) == 0) err = ERR_UNSUPPORTED; if (err == 0) { VirtualStream * stream = client->stream; if (client->pos == stream->pos && !stream->eos) { ReadRequest * r = loc_alloc_zero(sizeof(ReadRequest)); list_init(&r->link_client); r->client = client; r->size = size; strncpy(r->token, token, sizeof(r->token) - 1); list_add_last(&r->link_client, &client->read_requests); } else { assert(list_is_empty(&client->read_requests)); assert(client->channel == c); send_read_reply(client, token, size); advance_stream_buffer(stream); } } else { write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_stringz(&c->out, "null"); write_errno(&c->out, err); json_write_long(&c->out, 0); write_stream(&c->out, 0); json_write_boolean(&c->out, 0); write_stream(&c->out, 0); write_stream(&c->out, MARKER_EOM); } }
main() { DynamicList* l = list_inicialize(); /*Aluno* Al1 = (Aluno*)malloc(sizeof(Aluno)); Aluno* Al2 = (Aluno*)malloc(sizeof(Aluno)); Al1->RA = 1516; Al1->nome = "JOAO"; Al2->RA = 2324; Al2->nome = "SIBA"; */ printf("\nInseriu? %s", list_add_last(l, 'a')?"sim":"não"); printf("\nInseriu? %s", list_add_last(l, 'b')?"sim":"não"); printf("\nFirst %c\n", list_get_first(l)); printf("\nLast %c\n", list_get_last(l)); printf("\nInseriu? %s", list_add_last(l, 'c')?"sim":"não"); printf("\nInseriu? %s", list_add_last(l, 'd')?"sim":"não"); printf("\nInseriu? %s", list_add_first(l, 'e')?"sim":"não"); printf("\nInseriu? %s", list_add_first(l, 'f')?"sim":"não"); printf("\nInseriu? %s", list_add_first(l, 'g')?"sim":"não"); printf("\nFirst %c\n", list_get_first(l)); printf("\nLast %c\n", list_get_last(l)); list_print(l); printf("\nSize %d\n", list_size(l)); list_clear(l); printf("\nSize %d\n", list_size(l)); printf("\nInseriu? %s", list_add_last(l, 'c')?"sim":"não"); printf("\nInseriu? %s", list_add_last(l, 'd')?"sim":"não"); printf("\nInseriu? %s", list_add_first(l, 'e')?"sim":"não"); printf("\nInseriu? %s", list_add_first(l, 'f')?"sim":"não"); printf("\nInseriu? %s", list_add_first(l, 'g')?"sim":"não"); list_print(l); list_remove_first(l); list_remove_first(l); list_remove_first(l); list_print(l); }
struct task_t *task_start(task_func_t *task_func) { struct task_t *task = (struct task_t *)malloc_alloc(sizeof(struct task_t)); char *p = malloc_alloc(0x800); p += 0x800; task->sp = (uint32 *)(p); // 2k stack task->msg = 0; task->state = TASK_STATE_ACTIVE; list_init(&task->input_channels); list_init(&task->output_channels); task_create(&task->sp, task_func); list_add_last(active_tasks, task); print_buf("task start:"); print_buf(" t="); print_ptr(task); print_buf(" t->sp="); print_ptr(task->sp); print_buf("\n"); return task; }
static void event_attach_done(void * x) { AttachDoneArgs * args = (AttachDoneArgs *)x; if (context_find_from_pid(args->pid, 0) != NULL) { args->done(ERR_ALREADY_ATTACHED, NULL, args->data); } else { Context * ctx = NULL; if (parent_ctx == NULL) { pid_t pid = taskIdSelf(); parent_ctx = create_context(pid2id(pid, 0)); EXT(parent_ctx)->pid = pid; parent_ctx->mem = parent_ctx; parent_ctx->mem_access |= MEM_ACCESS_INSTRUCTION; parent_ctx->mem_access |= MEM_ACCESS_DATA; parent_ctx->big_endian = big_endian_host(); link_context(parent_ctx); send_context_created_event(parent_ctx); } assert(parent_ctx->ref_count > 0); ctx = create_context(pid2id(args->pid, EXT(parent_ctx)->pid)); EXT(ctx)->pid = args->pid; EXT(ctx)->regs = (REG_SET *)loc_alloc(sizeof(REG_SET)); ctx->mem = parent_ctx; ctx->big_endian = parent_ctx->big_endian; (ctx->parent = parent_ctx)->ref_count++; list_add_last(&ctx->cldl, &parent_ctx->children); link_context(ctx); trace(LOG_CONTEXT, "context: attached: ctx %#lx, id %#x", ctx, EXT(ctx)->pid); send_context_created_event(ctx); args->done(0, ctx, args->data); if (taskIsStopped(args->pid)) { struct event_info * info; ctx->pending_intercept = 1; info = event_info_alloc(EVENT_HOOK_STOP); if (info != NULL) { info->stopped_ctx.ctxId = args->pid; event_info_post(info); } } } loc_free(x); }
chunk_pool_t* chunk_pool_init(int fd, int prot) { //log_write(DEBUG, "chunk_pool_init: start of work); chunk_pool_t* cpool = (chunk_pool_t*)calloc(1, sizeof(chunk_pool_t)); if(!cpool) { //log_write(ERROR, "chunk_pool_init: cannot allocate memory); return NULL; } cpool->fd = fd; cpool->protection = prot; cpool->zero_chunks = list_init(); cpool->free_chunks = list_init(); cpool->hash = ht_init(DEFAULT_HASH_TABLE_SIZE, hash_fnv1a); cpool->loafs = (chunk_t**)calloc(1, sizeof(chunk_t*)); *cpool->loafs = (chunk_t*)calloc(DEFAULT_ARRAY_SIZE, sizeof(chunk_t)); cpool->loafs_count = 1; cpool->is_mapped = 0; cpool->pg_size = sysconf(_SC_PAGESIZE); sem_init(&cpool->semaphore, 0, 1); struct stat sb = {0}; int err = fstat(fd, &sb); cpool->file_size = sb.st_size; int i = 0; for(i; i < DEFAULT_ARRAY_SIZE; i++) { list_add_last(cpool->free_chunks, (value_t*)&(*cpool->loafs)[i]); } if(!cpool->hash || !cpool->zero_chunks || !cpool->free_chunks) { //log_write(ERROR, "chunk_pool_init: cannot allocate memory); return NULL; } return cpool; }
int chunk_release(chunk_t* chunk) { if(chunk == NULL) { return EINVAL; } int err = munmap(chunk->data, chunk->cpool->pg_size*(chunk->len)); if(err == -1) return errno; err = ht_del_item_by_key_and_value(chunk->cpool->hash, (hkey_t)chunk->index, (hvalue_t)chunk); if(err) return err; chunk->ref_counter = 0; chunk->index = 0; chunk->len = 0; chunk->data = NULL; err = list_add_last(chunk->cpool->free_chunks, (value_t)chunk); if(err) return err; return 0; }
int main(void) { linked_list_t *list = (linked_list_t*)malloc(sizeof(linked_list_t)); list_init(list); for (int i = 0; i < 10; i++){ char string[100]; sprintf(string, "Number: %d", i); list_add_first(list_create_node(i, string), list); list_add_last (list_create_node(i, string), list); } printf("Non-empty list\n"); list_print(list); list_clear(list); printf("Empty list\n"); list_print(list); list_free(list); free(list); return 0; }
static void channel_close_listener(Channel * c) { LINK list; LINK * list_next = NULL; list_init(&list); for (list_next = file_info_ring.next; list_next != &file_info_ring; list_next = list_next->next) { OpenFileInfo * h = ring2file(list_next); if (h->inp == &c->inp) { trace(LOG_ALWAYS, "file handle left open by client: FS%d", h->handle); list_remove(&h->link_hash); if (h->dir != NULL) { closedir(h->dir); h->dir = NULL; } if (h->file >= 0) { close(h->file); h->file = -1; while (!list_is_empty(&h->link_reqs)) { LINK * link = h->link_reqs.next; IORequest * req = reqs2req(link); list_remove(link); if (h->posted_req == req) { req->handle = NULL; } else { loc_free(req->info.u.fio.bufp); loc_free(req); } } } list_add_last(&h->link_hash, &list); } } while (!list_is_empty(&list)) delete_open_file_info(hash2file(list.next)); }
static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) { int stopped_by_exception = 0; unsigned long msg = 0; Context * ctx = NULL; Context * ctx2 = NULL; trace(LOG_EVENTS, "event: pid %d stopped, signal %d", pid, signal); ctx = context_find_from_pid(pid, 1); if (ctx == NULL) { ctx = find_pending(pid); if (ctx != NULL) { Context * prs = ctx; assert(prs->ref_count == 0); ctx = create_context(pid2id(pid, pid)); EXT(ctx)->pid = pid; EXT(ctx)->regs = (REG_SET *)loc_alloc(sizeof(REG_SET)); ctx->pending_intercept = 1; ctx->mem = prs; ctx->parent = prs; ctx->big_endian = prs->big_endian; prs->ref_count++; list_add_last(&ctx->cldl, &prs->children); link_context(prs); link_context(ctx); send_context_created_event(prs); send_context_created_event(ctx); if (EXT(prs)->attach_callback) { EXT(prs)->attach_callback(0, prs, EXT(prs)->attach_data); EXT(prs)->attach_callback = NULL; EXT(prs)->attach_data = NULL; } } } if (ctx == NULL) return; assert(!ctx->exited); assert(!EXT(ctx)->attach_callback); if (signal != SIGSTOP && signal != SIGTRAP) { sigset_set(&ctx->pending_signals, signal, 1); if (sigset_get(&ctx->sig_dont_stop, signal) == 0) { ctx->pending_intercept = 1; stopped_by_exception = 1; } } if (ctx->stopped) { send_context_changed_event(ctx); } else { thread_state_t state; unsigned int state_count; ContextAddress pc0 = 0; ContextAddress pc1 = 0; assert(!EXT(ctx)->regs_dirty); EXT(ctx)->end_of_step = 0; EXT(ctx)->ptrace_event = event; ctx->signal = signal; ctx->stopped_by_bp = 0; ctx->stopped_by_exception = stopped_by_exception; ctx->stopped = 1; if (EXT(ctx)->regs_error) { release_error_report(EXT(ctx)->regs_error); EXT(ctx)->regs_error = NULL; } else { pc0 = get_regs_PC(ctx); } if (thread_get_state(EXT(ctx)->pid, x86_THREAD_STATE32, EXT(ctx)->regs, &state_count) != KERN_SUCCESS) { assert(errno != 0); EXT(ctx)->regs_error = get_error_report(errno); trace(LOG_ALWAYS, "error: thread_get_state failed; id %s, error %d %s", ctx->id, errno, errno_to_str(errno)); } else { pc1 = get_regs_PC(ctx); } if (!EXT(ctx)->syscall_enter || EXT(ctx)->regs_error || pc0 != pc1) { EXT(ctx)->syscall_enter = 0; EXT(ctx)->syscall_exit = 0; EXT(ctx)->syscall_id = 0; EXT(ctx)->syscall_pc = 0; } trace(LOG_EVENTS, "event: pid %d stopped at PC = %#lx", pid, pc1); if (signal == SIGTRAP && event == 0 && !syscall) { size_t break_size = 0; get_break_instruction(ctx, &break_size); ctx->stopped_by_bp = !EXT(ctx)->regs_error && is_breakpoint_address(ctx, pc1 - break_size); EXT(ctx)->end_of_step = !ctx->stopped_by_bp && EXT(ctx)->pending_step; if (ctx->stopped_by_bp) set_regs_PC(ctx, pc1 - break_size); } EXT(ctx)->pending_step = 0; send_context_stopped_event(ctx); } }
error_t do_fork(fork_info_t *info) { kmem_req_t req; struct dqdt_attr_s attr; struct thread_s *child_thread; struct task_s *child_task; struct page_s *page; uint_t cid; error_t err; sint_t order; fork_dmsg(1, "%s: cpu %d, started [%d]\n", __FUNCTION__, cpu_get_id(), cpu_time_stamp()); child_thread = NULL; child_task = NULL; page = NULL; cid = info->cpu->cluster->id; attr.cid = cid; attr.cpu_id = 0; attr.cid_exec = info->cid_exec; //dqdt_update_threads_number(attr.cluster->levels_tbl[0], attr.cpu->lid, 1); dqdt_update_threads_number(cid, attr.cpu_id, 1); //attr.cluster = info->current_clstr; attr.cid = cid; err = task_create(&child_task, &attr, CPU_USR_MODE); //attr.cluster = info->cpu->cluster; attr.cid = cid; if(err) goto fail_task; fork_dmsg(1, "%s: cpu %d, ppid %d, task @0x%x, pid %d, task @0x%x [%d]\n", __FUNCTION__, cpu_get_id(), info->this_task->pid, info->this_task, child_task->pid, child_task, cpu_time_stamp()); req.type = KMEM_PAGE; req.size = ARCH_THREAD_PAGE_ORDER; req.flags = AF_KERNEL | AF_REMOTE; req.ptr = info->cpu->cluster; req.ptr = info->current_clstr; page = kmem_alloc(&req); if(page == NULL) goto fail_mem; fork_dmsg(1, "%s: child pid will be %d on cluster %d, cpu %d [%d]\n", __FUNCTION__, child_task->pid, child_task->cpu->cluster->id, child_task->cpu->gid, cpu_time_stamp()); err = task_dup(child_task, info->this_task); if(err) goto fail_task_dup; signal_manager_destroy(child_task); signal_manager_init(child_task); fork_dmsg(1, "%s: parent task has been duplicated [%d]\n", __FUNCTION__, cpu_time_stamp()); child_task->current_clstr = info->current_clstr; err = vmm_dup(&child_task->vmm, &info->this_task->vmm); if(err) goto fail_vmm_dup; fork_dmsg(1, "%s: parent vmm has been duplicated [%d]\n", __FUNCTION__, cpu_time_stamp()); child_thread = (struct thread_s*) ppm_page2addr(page); /* Set the child page before calling thread_dup */ child_thread->info.page = page; err = thread_dup(child_task, child_thread, info->cpu, info->cpu->cluster, info->this_thread); if(err) goto fail_thread_dup; /* Adjust child_thread attributes */ if(info->flags & PT_FORK_USE_AFFINITY) { child_thread->info.attr.flags |= (info->flags & ~(PT_ATTR_LEGACY_MASK)); if(!(info->flags & PT_ATTR_MEM_PRIO)) child_thread->info.attr.flags &= ~(PT_ATTR_MEM_PRIO); if(!(info->flags & PT_ATTR_AUTO_MGRT)) child_thread->info.attr.flags &= ~(PT_ATTR_AUTO_MGRT); if(!(info->flags & PT_ATTR_AUTO_NXTT)) child_thread->info.attr.flags &= ~(PT_ATTR_AUTO_NXTT); } fork_dmsg(1, "%s: parent current thread has been duplicated, tid %x [%d]\n", __FUNCTION__, child_thread, cpu_time_stamp()); if(info->isPinned) thread_migration_disabled(child_thread); else thread_migration_enabled(child_thread); list_add_last(&child_task->th_root, &child_thread->rope); child_task->threads_count = 1; child_task->threads_nr ++; child_task->state = TASK_READY; order = bitmap_ffs2(child_task->bitmap, 0, sizeof(child_task->bitmap)); if(order == -1) goto fail_order; bitmap_clear(child_task->bitmap, order); child_thread->info.attr.key = order; child_thread->info.order = order; child_task->next_order = order + 1; child_task->max_order = order; child_task->uid = info->this_task->uid; child_task->parent = info->this_task->pid; err = sched_register(child_thread); assert(err == 0); cpu_context_set_tid(&child_thread->info.pss, (reg_t)child_thread); cpu_context_set_pmm(&child_thread->info.pss, &child_task->vmm.pmm); cpu_context_dup_finlize(&child_thread->pws, &child_thread->info.pss); child_thread->info.retval = 0; child_thread->info.errno = 0; info->child_thread = child_thread; info->child_task = child_task; return 0; fail_order: fail_thread_dup: fail_vmm_dup: fail_task_dup: printk(WARNING, "WARNING: %s: destroy child thread\n", __FUNCTION__); req.ptr = page; kmem_free(&req); fail_mem: fail_task: //FIXME //dqdt_update_threads_number(attr.cluster->levels_tbl[0], attr.cpu->lid, -1); dqdt_update_threads_number(attr.cid, attr.cpu_id, -1); printk(WARNING, "WARNING: %s: destroy child task\n", __FUNCTION__); if(child_task != NULL) task_destroy(child_task); printk(WARNING, "WARNING: %s: fork err %d [%d]\n", __FUNCTION__, err, cpu_time_stamp()); return err; }
static PortServer * create_port_server(Channel * c, PortRedirectionInfo * redir) { int sock; struct sockaddr_in addr; PortAttribute * attr = redir->attrs; #if defined(_WRS_KERNEL) int addrlen; #else socklen_t addrlen; #endif u_short port_number; PortServer * server = NULL; int is_udp = 0; /* do we use a server UDP -or TCP- port? */ while (attr != NULL) { if (strcmp(attr->name, "Config") == 0) { ByteArrayInputStream buf; char * config; InputStream * inp = create_byte_array_input_stream(&buf, attr->value, strlen(attr->value)); config = json_read_alloc_string(inp); if (strncasecmp(config, "udp:", strlen("udp:")) == 0) { is_udp = 1; } loc_free(config); break; } attr = attr->next; } memset((void *) &addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = (u_short) htons(redir->local_port); sock = -1; if (is_udp) sock = socket(AF_INET, SOCK_DGRAM, 0); else if ((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0) set_socket_options(sock); /* set socket options */ if (sock == -1) return NULL ; if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { if (redir->local_port != 0) { memset((void *) &addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = (u_short) 0; if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror ("bind"); goto error; } } else { perror("bind"); goto error; } } if (!is_udp) { if (listen(sock, 16) != 0) goto error; } /* Get port property in case the default port could not be used or * the client specified a port that the system converts to a * dynamic port number. */ addrlen = sizeof addr; if (getsockname(sock, (struct sockaddr *) &addr, &addrlen) < 0) goto error; port_number = (u_short) ntohs(addr.sin_port); server = loc_alloc_zero(sizeof(PortServer)); server->sock = sock; server->is_udp = is_udp; #if defined(SOCK_MAXADDRLEN) server->addr_len = SOCK_MAXADDRLEN; #else server->addr_len = 0x1000; #endif server->addr_buf = (struct sockaddr *)loc_alloc(server->addr_len); server->local_port = port_number; if (!server->is_udp) { server->accept_in_progress = 1; server->accreq.done = port_server_accept_done; server->accreq.client_data = server; server->accreq.type = AsyncReqAccept; server->accreq.u.acc.sock = sock; server->accreq.u.acc.addr = server->addr_buf; server->accreq.u.acc.addrlen = server->addr_len; async_req_post(&server->accreq); } else { /* For UDP, automatically connect to the port since there is no * connection request we can detect. */ redir->auto_connect = 1; } list_add_last(&server->link, &server_list); channel_lock_with_msg(server->channel = c, channel_lock_svr_msg); snprintf (server->id, sizeof(server->id), "%" PRIu64, port_server_id++); return server; error: closesocket(sock); loc_free(server); return NULL ; }
static void command_write(char * token, Channel * c) { char id[256]; StreamClient * client = NULL; long size = 0; long offs = 0; char * data = NULL; int err = 0; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); size = json_read_long(&c->inp); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); client = find_client(id, c); if (client == NULL) err = errno; if (!err && (client->stream->access & VS_ENABLE_REMOTE_WRITE) == 0) err = ERR_UNSUPPORTED; { JsonReadBinaryState state; unsigned data_pos = 0; if (!err && !list_is_empty(&client->write_requests)) data = loc_alloc(size); json_read_binary_start(&state, &c->inp); for (;;) { if (data != NULL) { size_t rd = json_read_binary_data(&state, data + data_pos, size - offs - data_pos); if (rd == 0) break; data_pos += rd; } else { char buf[256]; size_t rd = json_read_binary_data(&state, buf, sizeof(buf)); if (rd == 0) break; if (!err) { size_t done = 0; if (virtual_stream_add_data(client->stream, buf, rd, &done, 0) < 0) err = errno; assert(done <= rd); offs += done; if (!err && done < rd) { data = loc_alloc(size - offs); memcpy(data, buf + done, rd - done); data_pos = rd - done; } } } } json_read_binary_end(&state); } if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); if (data != NULL) { WriteRequest * r = loc_alloc_zero(sizeof(WriteRequest)); list_init(&r->link_client); r->client = client; r->data = data; r->size = size - offs; strncpy(r->token, token, sizeof(r->token) - 1); list_add_last(&r->link_client, &client->write_requests); } else { write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, err); write_stream(&c->out, MARKER_EOM); } }
static void event_handler(void * arg) { struct event_info * info = (struct event_info *)arg; Context * current_ctx = context_find_from_pid(info->current_ctx.ctxId, 1); Context * stopped_ctx = context_find_from_pid(info->stopped_ctx.ctxId, 1); switch (info->event) { case EVENT_HOOK_BREAKPOINT: if (stopped_ctx == NULL) break; assert(!stopped_ctx->stopped); assert(!EXT(stopped_ctx)->regs_dirty); if (EXT(stopped_ctx)->regs_error) { release_error_report(EXT(stopped_ctx)->regs_error); EXT(stopped_ctx)->regs_error = NULL; } memcpy(EXT(stopped_ctx)->regs, &info->regs, sizeof(REG_SET)); EXT(stopped_ctx)->event = 0; stopped_ctx->signal = SIGTRAP; stopped_ctx->stopped = 1; stopped_ctx->stopped_by_bp = info->bp_info_ok; stopped_ctx->stopped_by_exception = 0; assert(get_regs_PC(stopped_ctx) == info->addr); if (stopped_ctx->stopped_by_bp && !is_breakpoint_address(stopped_ctx, info->addr)) { /* Break instruction that is not planted by us */ stopped_ctx->stopped_by_bp = 0; stopped_ctx->pending_intercept = 1; } EXT(stopped_ctx)->bp_info = info->bp_info; if (current_ctx != NULL) EXT(stopped_ctx)->bp_pid = EXT(current_ctx)->pid; assert(taskIsStopped(EXT(stopped_ctx)->pid)); trace(LOG_CONTEXT, "context: stopped by breakpoint: ctx %#lx, id %#x", stopped_ctx, EXT(stopped_ctx)->pid); send_context_stopped_event(stopped_ctx); break; case EVENT_HOOK_STEP_DONE: if (current_ctx == NULL) break; assert(!current_ctx->stopped); assert(!EXT(current_ctx)->regs_dirty); if (EXT(current_ctx)->regs_error) { release_error_report(EXT(current_ctx)->regs_error); EXT(current_ctx)->regs_error = NULL; } memcpy(EXT(current_ctx)->regs, &info->regs, sizeof(REG_SET)); EXT(current_ctx)->event = TRACE_EVENT_STEP; current_ctx->signal = SIGTRAP; current_ctx->stopped = 1; current_ctx->stopped_by_bp = 0; current_ctx->stopped_by_exception = 0; assert(taskIsStopped(EXT(current_ctx)->pid)); trace(LOG_CONTEXT, "context: stopped by end of step: ctx %#lx, id %#x", current_ctx, EXT(current_ctx)->pid); send_context_stopped_event(current_ctx); break; case EVENT_HOOK_STOP: if (stopped_ctx == NULL) break; assert(!stopped_ctx->exited); if (stopped_ctx->stopped) break; if (EXT(stopped_ctx)->regs_error) { release_error_report(EXT(stopped_ctx)->regs_error); EXT(stopped_ctx)->regs_error = NULL; } if (taskRegsGet(EXT(stopped_ctx)->pid, EXT(stopped_ctx)->regs) != OK) { EXT(stopped_ctx)->regs_error = get_error_report(errno); assert(EXT(stopped_ctx)->regs_error != NULL); } EXT(stopped_ctx)->event = 0; stopped_ctx->signal = SIGSTOP; stopped_ctx->stopped = 1; stopped_ctx->stopped_by_bp = 0; stopped_ctx->stopped_by_exception = 0; assert(taskIsStopped(EXT(stopped_ctx)->pid)); trace(LOG_CONTEXT, "context: stopped by sofware request: ctx %#lx, id %#x", stopped_ctx, EXT(stopped_ctx)->pid); send_context_stopped_event(stopped_ctx); break; case EVENT_HOOK_TASK_ADD: if (current_ctx == NULL) break; assert(stopped_ctx == NULL); stopped_ctx = create_context(pid2id((pid_t)info->stopped_ctx.ctxId, EXT(current_ctx->parent)->pid)); EXT(stopped_ctx)->pid = (pid_t)info->stopped_ctx.ctxId; EXT(stopped_ctx)->regs = (REG_SET *)loc_alloc(sizeof(REG_SET)); stopped_ctx->mem = current_ctx->mem; stopped_ctx->big_endian = current_ctx->mem->big_endian; (stopped_ctx->creator = current_ctx)->ref_count++; (stopped_ctx->parent = current_ctx->parent)->ref_count++; assert(stopped_ctx->mem == stopped_ctx->parent->mem); list_add_last(&stopped_ctx->cldl, &stopped_ctx->parent->children); link_context(stopped_ctx); trace(LOG_CONTEXT, "context: created: ctx %#lx, id %#x", stopped_ctx, EXT(stopped_ctx)->pid); send_context_created_event(stopped_ctx); break; default: assert(0); break; } loc_free(info); SPIN_LOCK_ISR_TAKE(&events_lock); events_cnt--; SPIN_LOCK_ISR_GIVE(&events_lock); }
static void * worker_thread_handler(void * x) { WorkerThread * wt = x; for (;;) { AsyncReqInfo * req = wt->req; assert(req != NULL); req->error = 0; switch(req->type) { case AsyncReqRead: /* File read */ req->u.fio.rval = read(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqWrite: /* File write */ req->u.fio.rval = write(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqSeekRead: /* File read at offset */ req->u.fio.rval = pread(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz, req->u.fio.offset); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqSeekWrite: /* File write at offset */ req->u.fio.rval = pwrite(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz, req->u.fio.offset); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqRecv: /* Socket recv */ req->u.sio.rval = recv(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags); if (req->u.sio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqSend: /* Socket send */ req->u.sio.rval = send(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags); if (req->u.sio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqRecvFrom: /* Socket recvfrom */ req->u.sio.rval = recvfrom(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags, req->u.sio.addr, &req->u.sio.addrlen); if (req->u.sio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqSendTo: /* Socket sendto */ req->u.sio.rval = sendto(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags, req->u.sio.addr, req->u.sio.addrlen); if (req->u.sio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqAccept: /* Accept socket connections */ req->u.acc.rval = accept(req->u.acc.sock, req->u.acc.addr, req->u.acc.addr ? &req->u.acc.addrlen : NULL); if (req->u.acc.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqConnect: /* Connect to socket */ req->u.acc.rval = connect(req->u.con.sock, req->u.con.addr, req->u.con.addrlen); if (req->u.con.rval == -1) { req->error = errno; assert(req->error); } break; /* Platform dependant IO methods */ #if defined(WIN32) #elif defined(_WRS_KERNEL) #else case AsyncReqWaitpid: /* Wait for process change */ req->u.wpid.rval = waitpid(req->u.wpid.pid, &req->u.wpid.status, req->u.wpid.options); if (req->u.con.rval == -1) { req->error = errno; assert(req->error); } break; #endif case AsyncReqSelect: { struct timeval tv; tv.tv_sec = (long)req->u.select.timeout.tv_sec; tv.tv_usec = req->u.select.timeout.tv_nsec / 1000; req->u.select.rval = select(req->u.select.nfds, &req->u.select.readfds, &req->u.select.writefds, &req->u.select.errorfds, &tv); if (req->u.con.rval == -1) { req->error = errno; assert(req->error); } break; } case AsyncReqClose: req->u.fio.rval = close(req->u.fio.fd); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; default: req->error = ENOSYS; break; } trace(LOG_ASYNCREQ, "async_req_complete: req %p, type %d, error %d", req, req->type, req->error); check_error(pthread_mutex_lock(&wtlock)); /* Post event inside lock to make sure a new worker thread is * not created unnecessarily */ post_event(req->done, req); wt->req = NULL; list_add_last(&wt->wtlink, &wtlist); for (;;) { check_error(pthread_cond_wait(&wt->cond, &wtlock)); if (wt->req != NULL) break; } check_error(pthread_mutex_unlock(&wtlock)); } }
void* kvfsd(void *arg) { uint_t tm_now, cntr; struct task_s *task; struct thread_s *this; struct cpu_s *cpu; struct alarm_info_s info; struct event_s event; uint_t fs_type; error_t err; cpu_enable_all_irq(NULL); printk(INFO, "INFO: Starting KVFSD on CPU %d [ %d ]\n", cpu_get_id(), cpu_time_stamp()); task = current_task; fs_type = VFS_TYPES_NR; #if CONFIG_ROOTFS_IS_EXT2 fs_type = VFS_EXT2_TYPE; #endif #if CONFIG_ROOTFS_IS_VFAT #if CONFIG_ROOTFS_IS_EXT2 #error More than one root fs has been selected #endif fs_type = VFS_VFAT_TYPE; #endif /* CONFIG_ROOTFS_IS_VFAT_TYPE */ err = vfs_init(__sys_blk, fs_type, VFS_MAX_NODE_NUMBER, VFS_MAX_FILE_NUMBER, &task->vfs_root); task->vfs_cwd = task->vfs_root; printk(INFO, "INFO: Virtual File System (VFS) Is Ready\n"); sysconf_init(); if(err == 0) { if((err = task_load_init(task))) { printk(WARNING, "WARNING: failed to load user process, err %d [%u]\n", err, cpu_time_stamp()); } } #if CONFIG_DEV_VERSION if(err != 0) { struct thread_s *thread; printk(INFO, "INFO: Creating kernel level terminal\n"); thread = kthread_create(task, &kMiniShelld, NULL, current_cluster->id, current_cpu->lid); thread->task = task; list_add_last(&task->th_root, &thread->rope); err = sched_register(thread); assert(err == 0); sched_add_created(thread); } #endif this = current_thread; cpu = current_cpu; event_set_senderId(&event, this); event_set_priority(&event, E_FUNC); event_set_handler(&event, &kvfsd_alarm_event_handler); info.event = &event; cntr = 0; while(1) { alarm_wait(&info, 10); sched_sleep(this); tm_now = cpu_time_stamp(); printk(INFO, "INFO: System Current TimeStamp %u\n", tm_now); sync_all_pages(); if((cntr % 4) == 0) dqdt_print_summary(dqdt_root); cntr ++; } return NULL; }
static ChannelNP * create_channel(noPollConn * np_sock, int en_ssl, int server) { const int i = 1; ChannelNP * c; int sock = nopoll_conn_socket(np_sock); assert(np_sock >= 0); if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&i, sizeof(i)) < 0) { int error = errno; trace(LOG_ALWAYS, "Can't set TCP_NODELAY option on a socket: %s", errno_to_str(error)); errno = error; return NULL; } if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&i, sizeof(i)) < 0) { int error = errno; trace(LOG_ALWAYS, "Can't set SO_KEEPALIVE option on a socket: %s", errno_to_str(error)); errno = error; return NULL; } c = (ChannelNP *)loc_alloc_zero(sizeof *c); #if ENABLE_Splice if (pipe(c->pipefd) == -1) { int err = errno; loc_free(c); trace(LOG_ALWAYS, "Cannot create channel pipe : %s", errno_to_str(err)); errno = err; return NULL; } #endif /* ENABLE_Splice */ c->magic = CHANNEL_MAGIC; c->is_ssl = en_ssl; c->chan.inp.read = np_read_stream; c->chan.inp.peek = np_peek_stream; c->obuf = output_queue_alloc_obuf(); c->chan.out.cur = c->obuf->buf; c->chan.out.end = c->obuf->buf + sizeof(c->obuf->buf); c->chan.out.write = np_write_stream; c->chan.out.write_block = np_write_block_stream; c->chan.out.splice_block = np_splice_block_stream; list_add_last(&c->chan.chanlink, &channel_root); shutdown_set_normal(&channel_shutdown); c->chan.state = ChannelStateStartWait; c->chan.incoming = server; c->chan.start_comm = start_channel; c->chan.check_pending = channel_check_pending; c->chan.message_count = channel_get_message_count; c->chan.lock = np_lock; c->chan.unlock = np_unlock; c->chan.is_closed = np_is_closed; c->chan.close = send_eof_and_close; ibuf_init(&c->ibuf, &c->chan.inp); c->ibuf.post_read = np_post_read; c->ibuf.wait_read = np_wait_read; c->ibuf.trigger_message = np_trigger_message; c->socket = nopoll_conn_socket(np_sock); c->np_socket = np_sock; c->lock_cnt = 1; c->rd_req.done = np_channel_read_done; c->rd_req.client_data = c; c->rd_req.type = AsyncReqSelect; #if ENABLE_OutputQueue output_queue_ini(&c->out_queue); #endif return c; }
void test_list(void) { int val[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; list me = list_init(sizeof(int)); assert(me); assert(list_size(me) == 0); assert(list_is_empty(me)); for (int i = 0; i < 10; i++) { list_add_first(me, &val[i]); assert(list_size(me) == i + 1); int get = 0; list_get_first(&get, me); assert(get == val[i]); } assert(list_size(me) == 10); assert(!list_is_empty(me)); int get_arr[10] = {0}; list_copy_to_array(get_arr, me); for (int i = 0; i < 10; i++) { int get = 0; list_get_at(&get, me, i); assert(get == val[9 - i]); assert(get_arr[i] == val[9 - i]); } for (int i = 0; i < 7; i++) { list_remove_last(me); } int trimmed[5] = {0}; list_copy_to_array(trimmed, me); assert(list_size(me) == 3); for (int i = 0; i < 3; i++) { assert(10 - i == trimmed[i]); } int add = 3; list_add_last(me, &add); add = -1; list_add_at(me, 1, &add); add = -2; list_add_last(me, &add); assert(list_size(me) == 6); int get = 0xdeadbeef; list_get_first(&get, me); assert(get == 10); get = 0xdeadbeef; list_get_at(&get, me, 0); assert(get == 10); list_get_at(&get, me, 1); assert(get == -1); list_get_at(&get, me, 2); assert(get == 9); list_get_at(&get, me, 3); assert(get == 8); list_get_at(&get, me, 4); assert(get == 3); list_get_at(&get, me, 5); assert(get == -2); get = 0xdeadbeef; list_get_last(&get, me); assert(get == -2); list_remove_first(me); list_remove_at(me, 2); list_remove_last(me); assert(list_size(me) == 3); get = 345; list_get_first(&get, me); assert(get == -1); list_get_at(&get, me, 1); assert(get == 9); list_get_last(&get, me); assert(get == 3); int set = 12; list_set_first(me, &set); set = 13; list_set_at(me, 1, &set); set = 14; list_set_last(me, &set); int arr[3] = {0}; list_copy_to_array(arr, me); assert(arr[0] == 12); assert(arr[1] == 13); assert(arr[2] == 14); set = -5; list_set_at(me, 0, &set); set = -6; list_set_at(me, 1, &set); set = -7; list_set_at(me, 2, &set); list_copy_to_array(arr, me); assert(arr[0] == -5); assert(arr[1] == -6); assert(arr[2] == -7); assert(list_set_at(me, 4, &set) == -EINVAL); assert(list_get_at(&set, me, 4) == -EINVAL); assert(list_remove_at(me, 4) == -EINVAL); assert(list_add_at(me, 5, &set) == -EINVAL); assert(list_set_at(me, -1, &set) == -EINVAL); assert(list_get_at(&set, me, -1) == -EINVAL); assert(list_remove_at(me, -1) == -EINVAL); assert(list_add_at(me, -1, &set) == -EINVAL); list_clear(me); assert(list_size(me) == 0); assert(list_is_empty(me)); assert(list_remove_first(me) == -EINVAL); assert(list_remove_last(me) == -EINVAL); me = list_destroy(me); assert(!me); }
static void * worker_thread_handler(void * x) { WorkerThread * wt = (WorkerThread *)x; for (;;) { AsyncReqInfo * req = wt->req; assert(req != NULL); req->error = 0; switch(req->type) { case AsyncReqTimer: #if defined(_WIN32) && !defined(__CYGWIN__) Sleep(EVENTS_TIMER_RESOLUTION); events_timer_ms = GetTickCount(); #else { struct timespec timenow; usleep(EVENTS_TIMER_RESOLUTION * 1000); if (clock_gettime(CLOCK_REALTIME, &timenow) == 0) { events_timer_ms = (uint32_t)(timenow.tv_nsec / 1000000 + timenow.tv_sec * 1000); } } #endif break; case AsyncReqRead: /* File read */ req->u.fio.rval = read(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqWrite: /* File write */ req->u.fio.rval = write(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqSeekRead: /* File read at offset */ req->u.fio.rval = pread(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz, (off_t)req->u.fio.offset); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqSeekWrite: /* File write at offset */ req->u.fio.rval = pwrite(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz, (off_t)req->u.fio.offset); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqRecv: /* Socket recv */ req->u.sio.rval = recv(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags); if (req->u.sio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqSend: /* Socket send */ req->u.sio.rval = send(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags); if (req->u.sio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqRecvFrom: /* Socket recvfrom */ req->u.sio.rval = recvfrom(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags, req->u.sio.addr, &req->u.sio.addrlen); if (req->u.sio.rval == -1) { req->error = errno; trace(LOG_ASYNCREQ, "AsyncReqRecvFrom: req %p, type %d, error %d", req, req->type, req->error); assert(req->error); } break; case AsyncReqSendTo: /* Socket sendto */ req->u.sio.rval = sendto(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags, req->u.sio.addr, req->u.sio.addrlen); if (req->u.sio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqAccept: /* Accept socket connections */ req->u.acc.rval = accept(req->u.acc.sock, req->u.acc.addr, req->u.acc.addr ? &req->u.acc.addrlen : NULL); if (req->u.acc.rval == -1) { req->error = errno; trace(LOG_ASYNCREQ, "AsyncReqAccept: req %p, type %d, error %d", req, req->type, req->error); assert(req->error); } break; case AsyncReqConnect: /* Connect to socket */ req->u.con.rval = connect(req->u.con.sock, req->u.con.addr, req->u.con.addrlen); if (req->u.con.rval == -1) { req->error = errno; trace(LOG_ASYNCREQ, "AsyncReqConnect: req %p, type %d, error %d", req, req->type, req->error); assert(req->error); } break; /* Platform dependant IO methods */ #if defined(_WIN32) || defined(__CYGWIN__) case AsyncReqConnectPipe: req->u.cnp.rval = ConnectNamedPipe(req->u.cnp.pipe, NULL); if (!req->u.cnp.rval) { req->error = set_win32_errno(GetLastError()); assert(req->error); } break; #elif defined(_WRS_KERNEL) #else case AsyncReqWaitpid: /* Wait for process change */ req->u.wpid.rval = waitpid(req->u.wpid.pid, &req->u.wpid.status, req->u.wpid.options); if (req->u.wpid.rval == -1) { req->error = errno; assert(req->error); } break; #endif case AsyncReqSelect: { struct timeval tv; tv.tv_sec = (long)req->u.select.timeout.tv_sec; tv.tv_usec = req->u.select.timeout.tv_nsec / 1000; req->u.select.rval = select(req->u.select.nfds, &req->u.select.readfds, &req->u.select.writefds, &req->u.select.errorfds, &tv); if (req->u.select.rval == -1) { req->error = errno; assert(req->error); } } break; case AsyncReqClose: req->u.fio.rval = close(req->u.fio.fd); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqCloseDir: req->u.dio.rval = closedir((DIR *)req->u.dio.dir); if (req->u.dio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqOpen: req->u.fio.rval = open(req->u.fio.file_name, req->u.fio.flags, req->u.fio.permission); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqOpenDir: req->u.dio.dir = opendir(req->u.dio.path); if (req->u.dio.dir == NULL) { req->error = errno; assert(req->error); } break; case AsyncReqFstat: memset(&req->u.fio.statbuf, 0, sizeof(req->u.fio.statbuf)); req->u.fio.rval = fstat(req->u.fio.fd, &req->u.fio.statbuf); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } #if defined(_WIN32) || defined(__CYGWIN__) req->u.fio.win32_attrs = req->error || !req->u.fio.file_name ? INVALID_FILE_ATTRIBUTES : GetFileAttributes(req->u.fio.file_name); #endif break; case AsyncReqStat: memset(&req->u.fio.statbuf, 0, sizeof(req->u.fio.statbuf)); req->u.fio.rval = stat(req->u.fio.file_name, &req->u.fio.statbuf); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } #if defined(_WIN32) || defined(__CYGWIN__) req->u.fio.win32_attrs = req->error ? INVALID_FILE_ATTRIBUTES : GetFileAttributes(req->u.fio.file_name); #endif break; case AsyncReqLstat: memset(&req->u.fio.statbuf, 0, sizeof(req->u.fio.statbuf)); req->u.fio.rval = lstat(req->u.fio.file_name, &req->u.fio.statbuf); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } #if defined(_WIN32) || defined(__CYGWIN__) req->u.fio.win32_attrs = req->error ? INVALID_FILE_ATTRIBUTES : GetFileAttributes(req->u.fio.file_name); #endif break; case AsyncReqSetStat: { int err = 0; if (req->u.fio.set_stat_flags & AsyncReqSetSize) { if (truncate(req->u.fio.file_name, (off_t)req->u.fio.statbuf.st_size) < 0) err = errno; } if (req->u.fio.set_stat_flags & AsyncReqSetPermissions) { if (chmod(req->u.fio.file_name, req->u.fio.statbuf.st_mode) < 0) err = errno; } #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WRS_KERNEL) # if defined(_WIN32) || defined(__CYGWIN__) if (req->u.fio.win32_attrs != INVALID_FILE_ATTRIBUTES) { if (SetFileAttributes(req->u.fio.file_name, req->u.fio.win32_attrs) == 0) err = set_win32_errno(GetLastError()); } # endif #else if (req->u.fio.set_stat_flags & AsyncReqSetUidGid) { if (chown(req->u.fio.file_name, req->u.fio.statbuf.st_uid, req->u.fio.statbuf.st_gid) < 0) err = errno; } #endif if (req->u.fio.set_stat_flags & AsyncReqSetAcModTime) { struct utimbuf buf; buf.actime = req->u.fio.statbuf.st_atime; buf.modtime = req->u.fio.statbuf.st_mtime; if (utime(req->u.fio.file_name, &buf) < 0) err = errno; } req->error = err; } break; case AsyncReqFSetStat: { int err = 0; if (req->u.fio.set_stat_flags & AsyncReqSetSize) { if (ftruncate(req->u.fio.fd, (off_t)req->u.fio.statbuf.st_size) < 0) err = errno; } #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WRS_KERNEL) if (req->u.fio.set_stat_flags & AsyncReqSetPermissions) { if (chmod(req->u.fio.file_name, req->u.fio.statbuf.st_mode) < 0) err = errno; } # if defined(_WIN32) || defined(__CYGWIN__) if (req->u.fio.win32_attrs != INVALID_FILE_ATTRIBUTES) { if (SetFileAttributes(req->u.fio.file_name, req->u.fio.win32_attrs) == 0) err = set_win32_errno(GetLastError()); } # endif #else if (req->u.fio.set_stat_flags & AsyncReqSetUidGid) { if (fchown(req->u.fio.fd, req->u.fio.statbuf.st_uid, req->u.fio.statbuf.st_gid) < 0) err = errno; } if (req->u.fio.set_stat_flags & AsyncReqSetPermissions) { if (fchmod(req->u.fio.fd, req->u.fio.statbuf.st_mode) < 0) err = errno; } #endif if (req->u.fio.set_stat_flags & AsyncReqSetAcModTime) { struct utimbuf buf; buf.actime = req->u.fio.statbuf.st_atime; buf.modtime = req->u.fio.statbuf.st_mtime; #if defined(_WIN32) && !defined(__MINGW32__) if (futime(req->u.fio.fd, &buf) < 0) err = errno; #else if (utime(req->u.fio.file_name, &buf) < 0) err = errno; #endif } req->error = err; } break; case AsyncReqRemove: req->u.fio.rval = remove(req->u.fio.file_name); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqReadDir: { int cnt = 0; while (cnt < req->u.dio.max_files) { char path[FILE_PATH_SIZE]; struct DirFileNode * file = req->u.dio.files + cnt; struct dirent * e; struct stat st; errno = 0; e = readdir((DIR *)req->u.dio.dir); if (e == NULL) { req->error = errno; if (req->error == 0) req->u.dio.eof = 1; break; } if (strcmp(e->d_name, ".") == 0) continue; if (strcmp(e->d_name, "..") == 0) continue; file->path = loc_strdup(e->d_name); memset(&st, 0, sizeof(st)); snprintf(path, sizeof(path), "%s/%s", req->u.dio.path, e->d_name); if (stat(path, &st) == 0) { #if defined(_WIN32) || defined(__CYGWIN__) file->win32_attrs = GetFileAttributes(path); #endif file->statbuf = (struct stat *)loc_alloc(sizeof(struct stat)); memcpy(file->statbuf, &st, sizeof(struct stat)); } cnt++; } } break; case AsyncReqRoots: { struct stat st; struct RootDevNode * newDevNode = NULL; #if defined(_WIN32) || defined(__CYGWIN__) { struct RootDevNode * curDevNode = NULL; int disk = 0; DWORD disks = GetLogicalDrives(); for (disk = 0; disk <= 30; disk++) { if (disks & (1 << disk)) { char path[32]; newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode)); if (curDevNode == NULL) req->u.root.lst = newDevNode; else curDevNode->next = newDevNode; curDevNode = newDevNode; snprintf(path, sizeof(path), "%c:\\", 'A' + disk); newDevNode->devname = loc_strdup(path); if (disk >= 2) { ULARGE_INTEGER total_number_of_bytes; BOOL has_size = GetDiskFreeSpaceExA(path, NULL, &total_number_of_bytes, NULL); memset(&st, 0, sizeof(st)); #if defined(__CYGWIN__) snprintf(path, sizeof(path), "/cygdrive/%c", 'a' + disk); #endif if (has_size && stat(path, &st) == 0) { newDevNode->win32_attrs = GetFileAttributes(path); newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat)); memcpy(newDevNode->statbuf, &st, sizeof(struct stat)); } } } } } #elif defined(_WRS_KERNEL) { struct RootDevNode * curDevNode = NULL; extern DL_LIST iosDvList; DEV_HDR * dev; for (dev = (DEV_HDR *)DLL_FIRST(&iosDvList); dev != NULL; dev = (DEV_HDR *)DLL_NEXT(&dev->node)) { char path[FILE_PATH_SIZE]; if (strcmp(dev->name, "host:") == 0) { /* Windows host is special case */ int d; for (d = 'a'; d < 'z'; d++) { snprintf(path, sizeof(path), "%s%c:/", dev->name, d); if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode)); if (curDevNode == NULL) req->u.root.lst = newDevNode; else curDevNode->next = newDevNode; curDevNode = newDevNode; newDevNode->devname = loc_strdup(path); newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat)); memcpy(newDevNode->statbuf, &st, sizeof(struct stat)); } } } snprintf(path, sizeof(path), "%s/", dev->name); if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode)); if (curDevNode == NULL) req->u.root.lst = newDevNode; else curDevNode->next = newDevNode; curDevNode = newDevNode; newDevNode->devname = loc_strdup(path); newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat)); memcpy(newDevNode->statbuf, &st, sizeof(struct stat)); } } } #else req->u.root.lst = newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode)); newDevNode->devname = loc_strdup("/"); if (stat("/", &st) == 0) { newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat)); memcpy(newDevNode->statbuf, &st, sizeof(struct stat)); } #endif } break; case AsyncReqUser: /* User defined request */ req->u.user.rval = req->u.user.func(req->u.user.data); if (req->u.user.rval == -1) { req->error = errno; assert(req->error); } break; default: req->error = ENOSYS; break; } if (req->type == AsyncReqTimer) { if (async_shutdown.state == SHUTDOWN_STATE_PENDING) break; continue; } trace(LOG_ASYNCREQ, "async_req_complete: req %p, type %d, error %d", req, req->type, req->error); check_error(pthread_mutex_lock(&wtlock)); /* Post event inside lock to make sure a new worker thread is not created unnecessarily */ post_event(req->done, req); wt->req = NULL; if (wtlist_size >= MAX_WORKER_THREADS || async_shutdown.state == SHUTDOWN_STATE_PENDING) { check_error(pthread_mutex_unlock(&wtlock)); break; } list_add_last(&wt->wtlink, &wtlist); wtlist_size++; for (;;) { check_error(pthread_cond_wait(&wt->cond, &wtlock)); if (wt->req != NULL) break; } check_error(pthread_mutex_unlock(&wtlock)); if (wt->req == &shutdown_req) break; } post_event(worker_thread_exit, wt); return NULL; }
int virtual_stream_write(Channel * c, char * token, char * id, size_t size, InputStream * inp) { char * data = NULL; int err = 0; long offs = 0; StreamClient * client = find_client(id, c); if (client == NULL) err = errno; if (!err && (client->stream->access & VS_ENABLE_REMOTE_WRITE) == 0) err = ERR_UNSUPPORTED; { JsonReadBinaryState state; size_t data_pos = 0; if (!err && !list_is_empty(&client->write_requests)) data = (char *)loc_alloc(size); json_read_binary_start(&state, inp); for (;;) { if (data != NULL) { size_t rd = json_read_binary_data(&state, data + data_pos, size - offs - data_pos); if (rd == 0) break; data_pos += rd; } else { char buf[256]; size_t rd = json_read_binary_data(&state, buf, sizeof(buf)); if (rd == 0) break; if (!err) { size_t done = 0; if (virtual_stream_add_data(client->stream, buf, rd, &done, 0) < 0) err = errno; assert(done <= rd); offs += done; if (!err && done < rd) { data = (char *)loc_alloc(size - offs); memcpy(data, buf + done, rd - done); data_pos = rd - done; } } } } json_read_binary_end(&state); } if (data != NULL) { WriteRequest * r = (WriteRequest *)loc_alloc_zero(sizeof(WriteRequest)); list_init(&r->link_client); r->client = client; r->data = data; r->size = size - offs; strlcpy(r->token, token, sizeof(r->token)); list_add_last(&r->link_client, &client->write_requests); } else if (err == 0) { write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, err); write_stream(&c->out, MARKER_EOM); } if (err != 0) errno = err; return err == 0 ? 0 : -1; }
static PortServer * create_server(Channel * c, PortAttribute * attrs) { int sock = -1; struct sockaddr_in addr; PortAttribute * attr = attrs; #if defined(_WRS_KERNEL) int addrlen; #else socklen_t addrlen; #endif u_short port_number; PortServer * server = NULL; int is_udp = 0; /* do we use a server UDP -or TCP- port? */ char * port_config = NULL; int error = 0; int auto_connect = 0; uint64_t auto_connect_period = 0; unsigned int local_port = 0; while (attr != NULL) { if (strcmp(attr->name, "Port") == 0) { ByteArrayInputStream buf; InputStream * inp = create_byte_array_input_stream(&buf, attr->value, strlen(attr->value)); port_config = json_read_alloc_string(inp); if (strncasecmp(port_config, "udp:", strlen("udp:")) == 0) { is_udp = 1; } } else if (strcmp(attr->name, "AutoConnect") == 0) { ByteArrayInputStream buf; InputStream * inp = create_byte_array_input_stream(&buf, attr->value, strlen(attr->value)); auto_connect = json_read_boolean(inp); } else if (strcmp(attr->name, "AutoConnectPeriod") == 0) { ByteArrayInputStream buf; InputStream * inp = create_byte_array_input_stream(&buf, attr->value, strlen(attr->value)); auto_connect_period = json_read_ulong(inp); } else if (strcmp(attr->name, "LocalPort") == 0) { ByteArrayInputStream buf; InputStream * inp = create_byte_array_input_stream(&buf, attr->value, strlen(attr->value)); local_port = (unsigned int) json_read_uint64(inp); } attr = attr->next; } if (port_config == NULL) { error = set_errno(ERR_OTHER, "No port configuration is specified"); } if (error == 0) { loc_free(port_config); memset((void *) &addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = (u_short) htons(local_port); if (is_udp) sock = socket(AF_INET, SOCK_DGRAM, 0); else if ((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0) set_socket_options(sock); /* set socket options */ if (sock == -1) error = errno; } if (error == 0) { if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { error = errno; } } if (error == 0 && !is_udp) { if (listen(sock, 16) != 0) error = errno; } if (error == 0) { /* Get port property in case the default port could not be used or * the client specified a port that the system converts to a * dynamic port number. */ addrlen = sizeof addr; if (getsockname(sock, (struct sockaddr *) &addr, &addrlen) < 0) error = errno; } if (error == 0) { port_number = (u_short) ntohs(addr.sin_port); server = (PortServer *)loc_alloc_zero(sizeof(PortServer)); server->sock = sock; server->is_udp = is_udp; #if defined(SOCK_MAXADDRLEN) server->addr_len = SOCK_MAXADDRLEN; #else server->addr_len = 0x1000; #endif server->addr_buf = (struct sockaddr *)loc_alloc(server->addr_len); server->local_port = port_number; if (!server->is_udp) { server->accept_in_progress = 1; server->auto_connect = auto_connect; server->accreq.done = port_server_accept_done; server->accreq.client_data = server; server->accreq.type = AsyncReqAccept; server->accreq.u.acc.sock = sock; server->accreq.u.acc.addr = server->addr_buf; server->accreq.u.acc.addrlen = server->addr_len; async_req_post(&server->accreq); } else { /* For UDP, automatically connect to the port since there is no * connection request we can detect. */ server->auto_connect = 1; } server->auto_connect_period = auto_connect_period; list_add_last(&server->link, &server_list); channel_lock_with_msg(server->channel = c, channel_lock_svr_msg); snprintf (server->id, sizeof(server->id), "PS%" PRIu64, port_server_id++); server->attrs = attrs; } if (error == 0) return server; else { if (sock != -1) closesocket(sock); loc_free(server); return NULL ; } }