Пример #1
0
void nx_window_delete(nx_window *self)
{
	if(nx_thread_is_running(self->thread))
		nx_window_close(self);

	nx_thread_end(self->thread);

	nx_event_source_delete(self->event_source);

	nx_free(self->title);

	nx_free(self);
}
Пример #2
0
struct nx_thread_t* nx_thread_begin(nx_thread_proc proc, void *param)
{
	struct nx_thread_t *thread;
	pthread_attr_t attribute;

	if(!proc)
		return 0;

	thread = nx_malloc(sizeof(nx_thread));

	thread->proc = proc;
	thread->param = param; 
	thread->time_to_quit = nxfalse;
	thread->is_running = nxfalse;

	pthread_attr_init(&attribute);
	if(pthread_attr_setdetachstate(&attribute, PTHREAD_CREATE_JOINABLE) == 0)
	{
		if(pthread_create(&thread->handle,
					      &attribute,
					      (void *(*) (void *))&_nx_thread_exec,
					      thread) == 0)
			return thread;
	}

	nx_free(thread);
	return 0;
}
Пример #3
0
void nx_thread_end(nx_thread *self)
{
	if(nx_thread_is_running(self))
		nx_thread_quit(self);

	nx_thread_wait(self,0);

	nx_free(self); 
}
Пример #4
0
/* This is where most of the magic happens. This function gets called
 * every millisecond to handle scheduling decisions.
 */
static void scheduler_cb(void) {
  U32 time = nx_systick_get_ms();
  bool need_reschedule = FALSE;

  /* Security mechanism: in case the system crashes, as long as the
   * scheduler is still running, the brick can be powered off.
   */
  if (nx_avr_get_button() == BUTTON_CANCEL)
    nx_core_halt();

  /* If the scheduler state is locked, nothing can be done. */
  if (sched_lock > 0)
    return;

  sched_lock = 1;

  /* Process pending commands, if any */
  if (task_command != CMD_NONE) {
    switch (task_command) {
    case CMD_YIELD:
      need_reschedule = TRUE;
      break;
    case CMD_DIE:
      destroy_running_task();
      need_reschedule = TRUE;
      break;
    default:
      break;
    }
    task_command = CMD_NONE;
    nx_systick_unmask_scheduler();
  } else {
    /* Check if the task quantum for the running task has expired. */
    if (time - sched_state.last_context_switch >= TASK_EXECUTION_QUANTUM)
      need_reschedule = TRUE;
  }

  /* Wake up tasks that have scheduled alarms. */
  while (!mv_list_is_empty(sched_state.alarms_pending) &&
         sched_state.alarms_pending->wakeup_time <= time) {
    struct mv_alarm_entry *a = sched_state.alarms_pending;
    mv_list_remove(sched_state.alarms_pending, sched_state.alarms_pending);
    mv__scheduler_task_unblock(a->task);
    nx_free(a);
  }

  /* Task switching time? */
  if (need_reschedule) {
    if (sched_state.task_current != NULL)
      sched_state.task_current->stack_current = mv__task_get_stack();
    reschedule();
    mv__task_set_stack(sched_state.task_current->stack_current);
    sched_state.last_context_switch = nx_systick_get_ms();
  }

  sched_lock = 0;
}
Пример #5
0
void nxp_finalize(nxp_pool* pool) {
  nxp_chunk* c=pool->chunk;
  nxp_chunk* cp;
  int cnt=0;
  while (c!=pool->initial_chunk) {
    cp=c->prev;
    nx_free(c);
    cnt++;
    c=cp;
  }
}
Пример #6
0
nxweb_result nxweb_cache_try(nxweb_http_server_connection* conn, nxweb_http_response* resp, const char* key, time_t if_modified_since, time_t revalidated_mtime) {
  if (*key==' ' || *key=='*') return NXWEB_MISS; // not implemented yet
  nxe_time_t loop_time=nxweb_get_loop_time(conn);
  ah_iter_t ci;
  //nxweb_log_error("trying cache for %s", fpath);
  pthread_mutex_lock(&_nxweb_cache_mutex);
  if ((ci=alignhash_get(nxweb_cache, _nxweb_cache, key))!=alignhash_end(_nxweb_cache)) {
    nxweb_cache_rec* rec=alignhash_value(_nxweb_cache, ci);
    if (rec->last_modified==revalidated_mtime) {
      rec->expires_time=loop_time+NXWEB_DEFAULT_CACHED_TIME;
      nxweb_log_info("revalidated %s in memcache", key);
    }
    if (loop_time <= rec->expires_time) {
      if (rec!=_nxweb_cache_head) {
        cache_rec_unlink(rec);
        cache_rec_link(rec); // relink to head
      }
      if (if_modified_since && rec->last_modified<=if_modified_since) {
        pthread_mutex_unlock(&_nxweb_cache_mutex);
        resp->status_code=304;
        resp->status="Not Modified";
        return NXWEB_OK;
      }
      rec->ref_count++; // this must be within mutex-protected section
      pthread_mutex_unlock(&_nxweb_cache_mutex);
      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;
      conn->hsp.req_data=rec;
      conn->hsp.req_finalize=cache_rec_unref;
      return NXWEB_OK;
    }
    else if (!revalidated_mtime) {
      pthread_mutex_unlock(&_nxweb_cache_mutex);
      return NXWEB_REVALIDATE;
    }
    alignhash_del(nxweb_cache, _nxweb_cache, ci);
    cache_rec_unlink(rec);
    if (!rec->ref_count) {
      nx_free(rec);
    }
    else {
      // this is normal; just notification
      nxweb_log_error("removed %s [%p] from cache while its ref_count=%d", key, rec, rec->ref_count);
    }
  }
  pthread_mutex_unlock(&_nxweb_cache_mutex);
  return NXWEB_MISS;
}
Пример #7
0
static void cache_finalize() {
  ah_iter_t ci;
  for (ci=alignhash_begin(_nxweb_cache); ci!=alignhash_end(_nxweb_cache); ci++) {
    if (alignhash_exist(_nxweb_cache, ci)) {
      nxweb_cache_rec* rec=alignhash_value(_nxweb_cache, ci);
      if (rec->ref_count) nxweb_log_error("file %s still in cache with ref_count=%d", alignhash_key(_nxweb_cache, ci), rec->ref_count);
      cache_rec_unlink(rec);
      nx_free(rec);
    }
  }
  alignhash_destroy(nxweb_cache, _nxweb_cache);
  pthread_mutex_destroy(&_nxweb_cache_mutex);
}
Пример #8
0
void mv_semaphore_inc(mv_sem_t *sem) {
  mv_scheduler_lock();
  sem->count++;

  /* If we are/were beyond what the semaphore can handle, we need to
   * wake up one of the blocked tasks.
   */
  if (sem->count <= 0) {
    struct sem_task_handle *h = mv_list_pop_head(sem->blocked_tasks);
    mv__scheduler_task_unblock(h->task);
    nx_free(h);
  }

  mv_scheduler_unlock();
}
Пример #9
0
static inline void cache_check_size() {
  while (alignhash_size(_nxweb_cache)>NXWEB_MAX_CACHED_ITEMS) {
    nxweb_cache_rec* rec=_nxweb_cache_tail;
    while (rec && rec->ref_count) rec=rec->prev;
    if (rec) {
      const char* fpath=rec->content+rec->content_length+1;
      ah_iter_t ci=alignhash_get(nxweb_cache, _nxweb_cache, fpath);
      if (ci!=alignhash_end(_nxweb_cache)) {
        assert(rec==alignhash_value(_nxweb_cache, ci));
        cache_rec_unlink(rec);
        alignhash_del(nxweb_cache, _nxweb_cache, ci);
        nx_free(rec);
      }
    }
    else {
      break;
    }
  }
}
Пример #10
0
void nxp_gc(nxp_pool* pool) {
  if (!pool->chunk->prev) return; // can't free the very first chunk

  nxp_object *obj;
  int object_size=pool->object_size;
  int i;
  for (obj=pool->chunk->pool, i=pool->chunk->nitems; i>0; i--, obj=(nxp_object*)((char*)obj+object_size)) {
    if (obj->in_use) return;
  }
  // all objects in last chunk are not in use
  // => remove them from free list and free the chunk
  for (obj=pool->chunk->pool, i=pool->chunk->nitems; i>0; i--, obj=(nxp_object*)((char*)obj+object_size)) {
    if (obj->prev) obj->prev->next=obj->next;
    else pool->free_first=obj->next;
    if (obj->next) obj->next->prev=obj->prev;
    else pool->free_last=obj->prev;
  }
  nxp_chunk* c=pool->chunk;
  pool->chunk=pool->chunk->prev;
  nx_free(c);
}
Пример #11
0
static void cache_rec_unref(nxd_http_server_proto* hsp, void* req_data) {
  pthread_mutex_lock(&_nxweb_cache_mutex);
  nxweb_cache_rec* rec=req_data;
  assert(rec->ref_count>0);
  if (!--rec->ref_count) {
    nxe_time_t loop_time=_nxweb_net_thread_data->loop->current_time;
    if (loop_time > rec->expires_time || !IS_LINKED(rec)) {
      const char* fpath=rec->content+rec->content_length+1;
      ah_iter_t ci=alignhash_get(nxweb_cache, _nxweb_cache, fpath);
      if (ci!=alignhash_end(_nxweb_cache) && rec==alignhash_value(_nxweb_cache, ci)) {
        alignhash_del(nxweb_cache, _nxweb_cache, ci);
        cache_rec_unlink(rec);
      }
      else {
        nxweb_log_error("freed previously removed cache entry %s [%p]", fpath, rec);
      }
      nx_free(rec);
    }
  }
  cache_check_size();
  pthread_mutex_unlock(&_nxweb_cache_mutex);
}
Пример #12
0
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;
}
Пример #13
0
void nxp_destroy(nxp_pool* pool) {
  nxp_finalize(pool);
  nx_free(pool);
}
Пример #14
0
void _nx_delete_wcex(WNDCLASSEX *wcex)
{
	UnregisterClass(wcex->lpszClassName,GetModuleHandle(0));
	nx_free((void*)wcex->lpszClassName);
}
Пример #15
0
/* Destroy the task that was just preempted. */
static inline void destroy_running_task(void) {
  mv_list_remove(sched_state.tasks_ready, sched_state.task_current);
  nx_free(sched_state.task_current->stack_base);
  nx_free(sched_state.task_current);
  sched_state.task_current = NULL;
}
Пример #16
0
void mv_semaphore_destroy(mv_sem_t *sem) {
  mv_scheduler_lock();
  NX_ASSERT(sem->count >= 0);
  nx_free(sem);
  mv_scheduler_unlock();
}