mv_sem_t *mv_semaphore_create(S32 count) { mv_sem_t *sem; NX_ASSERT(count >= 0); sem = nx_calloc(1, sizeof(*sem)); sem->count = count; mv_list_init(sem->blocked_tasks); return sem; }
/* Build a new task descriptor for a task that will run the given * function when activated. */ static mv_task_t *new_task(nx_closure_t func, U32 stack_size) { mv_task_t *t; nx_task_stack_t *s; NX_ASSERT_MSG((stack_size & 0x3) == 0, "Stack must be\n4-byte aligned"); t = nx_calloc(1, sizeof(*t)); t->stack_base = nx_calloc(1, stack_size); t->stack_current = (U32*) ((U32)t->stack_base + stack_size - sizeof(*s)); s = (nx_task_stack_t*)t->stack_current; s->pc = (U32) func; s->lr = (U32) task_shutdown; s->cpsr = MODE_SYS; if (s->pc & 0x1) { s->pc &= 0xFFFFFFFE; s->cpsr |= 0x20; } t->state = READY; mv_list_init_singleton(t, t); return t; }
void mv__scheduler_task_suspend(U32 time) { struct mv_alarm_entry *a; mv_scheduler_lock(); NX_ASSERT(sched_state.task_current->state == READY); /* Prepare the alarm descriptor. */ a = nx_calloc(1, sizeof(*a)); a->wakeup_time = nx_systick_get_ms() + time; a->task = sched_state.task_current; mv__scheduler_task_block(); /* If the alarm list is empty, the initialization is * trivial. Otherwise, we need to locate the correct place in the list * for a sorted insertion. */ if (mv_list_is_empty(sched_state.alarms_pending)) { mv_list_init_singleton(sched_state.alarms_pending, a); } else if (a->wakeup_time <= sched_state.alarms_pending->wakeup_time) { mv_list_add_head(sched_state.alarms_pending, a); } else if (a->wakeup_time >= sched_state.alarms_pending->prev->wakeup_time) { mv_list_add_tail(sched_state.alarms_pending, a); } else { struct mv_alarm_entry *ptr = sched_state.alarms_pending; while(ptr->next->wakeup_time < a->wakeup_time) ptr = ptr->next; mv_list_insert_after(ptr, a); } /* The alarm is programmed and the task configured to block. It will * be preempted when the scheduler completely unlocks. */ mv_scheduler_unlock(); }
nxweb_result nxweb_cache_store_response(nxweb_http_server_connection* conn, nxweb_http_response* resp) { nxe_time_t loop_time=nxweb_get_loop_time(conn); if (!resp->status_code) resp->status_code=200; if (resp->status_code==200 && resp->sendfile_path // only cache content from files && resp->content_length>=0 && resp->content_length<=NXWEB_MAX_CACHED_ITEM_SIZE // must be small && resp->sendfile_offset==0 && resp->sendfile_end==resp->content_length // whole file only && resp->sendfile_end>=resp->sendfile_info.st_size // st_size could be zero if not initialized && alignhash_size(_nxweb_cache)<NXWEB_MAX_CACHED_ITEMS+16) { const char* fpath=resp->sendfile_path; const char* key=resp->cache_key; if (nxweb_cache_try(conn, resp, key, 0, resp->last_modified)!=NXWEB_MISS) return NXWEB_OK; nxweb_cache_rec* rec=nx_calloc(sizeof(nxweb_cache_rec)+resp->content_length+1+strlen(key)+1); rec->expires_time=loop_time+NXWEB_DEFAULT_CACHED_TIME; rec->last_modified=resp->last_modified; rec->content_type=resp->content_type; // assume content_type and content_charset come rec->content_charset=resp->content_charset; // from statically allocated memory, which won't go away rec->content_length=resp->content_length; rec->gzip_encoded=resp->gzip_encoded; char* ptr=((char*)rec)+offsetof(nxweb_cache_rec, content); int fd; if ((fd=open(fpath, O_RDONLY))<0 || read(fd, ptr, resp->content_length)!=resp->content_length) { if (fd>0) close(fd); nx_free(rec); nxweb_log_error("nxweb_cache_file_store_and_send(): [%s] stat() was OK, but open/read() failed", fpath); nxweb_send_http_error(resp, 500, "Internal Server Error"); return NXWEB_ERROR; } close(fd); resp->content=ptr; ptr+=resp->content_length; *ptr++='\0'; strcpy(ptr, key); key=ptr; int ret=0; ah_iter_t ci; pthread_mutex_lock(&_nxweb_cache_mutex); ci=alignhash_set(nxweb_cache, _nxweb_cache, key, &ret); if (ci!=alignhash_end(_nxweb_cache)) { if (ret!=AH_INS_ERR) { alignhash_value(_nxweb_cache, ci)=rec; cache_rec_link(rec); rec->ref_count++; cache_check_size(); pthread_mutex_unlock(&_nxweb_cache_mutex); nxweb_log_info("memcached %s", key); conn->hsp.req_data=rec; assert(!conn->hsp.req_finalize); conn->hsp.req_finalize=cache_rec_unref; //nxweb_start_sending_response(conn, resp); return NXWEB_OK; } else { // AH_INS_ERR => key already exists (added by other thread) nx_free(rec); rec=alignhash_value(_nxweb_cache, ci); resp->content_length=rec->content_length; resp->content=rec->content; resp->content_type=rec->content_type; resp->content_charset=rec->content_charset; resp->last_modified=rec->last_modified; resp->gzip_encoded=rec->gzip_encoded; rec->ref_count++; pthread_mutex_unlock(&_nxweb_cache_mutex); conn->hsp.req_data=rec; assert(!conn->hsp.req_finalize); conn->hsp.req_finalize=cache_rec_unref; //nxweb_start_sending_response(conn, resp); return NXWEB_OK; } } pthread_mutex_unlock(&_nxweb_cache_mutex); nx_free(rec); } return NXWEB_OK; }
static struct sem_task_handle *make_sem_task_handle(mv_task_t *task) { struct sem_task_handle *h = nx_calloc(1, sizeof(*h)); h->task = task; return h; }