⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys_arch.c

📁 lwip tcp/ip 协议栈 adsp BF533 DSP 移植 用 visual dsp++ 编译
💻 C
字号:
#include "lwip/debug.h"

#include "lwip/sys.h"
#include "lwip/opt.h"
#include "lwip/stats.h"
#include <stdlib.h>
#include <string.h>

// information about each thread that lwIP creates
#include "sys_arch_thread.h"
#include <cglobals.h>
#include <kernel_abs.h>

// information about each mailbox that lwIP creates
//
#define SYS_MBOX_SIZE   128      // number of elements per mbox queue
struct sys_arch_mbox {
  ker_sem_id_t  id;
  s16_t           count;                // number of messages in queue
  s16_t           rndx;                 // index of next message to read
  s16_t           wndx;                 // index of next message to write
  void*           msgs[SYS_MBOX_SIZE];  // the message queue
};

// head of lists of all thread structs, active or free
//
static struct   sys_arch_thread* thread_list;
static volatile sys_prot_t prot_level;

void
sys_init(void)
{
  thread_list = NULL;
  prot_level = 0; // presumably
}

//--------------------------------------------------------------------------
static struct sys_arch_thread*
new_sys_arch_thread(ker_thread_id_t id, void (*function)(void *arg), void *arg)
{
  struct sys_arch_thread* t;
  sys_prot_t old_level;

  t = (struct sys_arch_thread*)calloc(1, sizeof(struct sys_arch_thread));
  LWIP_ASSERT("new_sys_arch_thread: struct allocated", t != NULL);

  t->id = id;
  t->function = function;
  t->arg = arg;

  old_level = sys_arch_protect();

  t->next = thread_list;
  thread_list = t;

  sys_arch_unprotect(old_level);

  return t;
}

//--------------------------------------------------------------------------
sys_thread_t
sys_thread_new(void (*function)(void *arg), void *arg, int prio)
{
  struct sys_arch_thread* t;
  sys_prot_t old_level;

  old_level = sys_arch_protect();

  // find a free sys_arch_thread struct or create a new one
  t = thread_list;
  while (t) {
    if (t->id == (ker_thread_id_t)UINT_MAX) {
      // stop optimiser throwing this assignment away
      *(volatile ker_thread_id_t*)&t->id = (ker_thread_id_t)(UINT_MAX - 1);
      break;
    }
    t = t->next;
  }

  if (t == NULL) {
    t = new_sys_arch_thread((ker_thread_id_t)(UINT_MAX - 1), function, arg);
  } else {
    t->function = function;
    t->arg = arg;
  }

  	 ker_create_thread((void*)function,(void*)arg,0,0,prio,"L",(ker_thread_id_t*)&t->id);
  sys_arch_unprotect(old_level);

//  LWIP_ASSERT("sys_thread_new: create thread failed", MR_SUCCESS(mr));
  return t;
}

//--------------------------------------------------------------------------
// this function either finds the currently running VDK thread in the list
// of sys_arch_threads or creates a new entry for it
//
// the function is global so that ErrorFunction() in VDK threads not created
// by sys_thread_new() can duplicate the action of ADI_TOOLS_IOEThread's 
// function when a sys_arch_sem_wait() or sys_arch_mbox_fetch() times out; 
// also the
// Destroy() function in such threads can mark the sys_arch_thread as free
// and thus avoid a memory leak
//
struct sys_arch_thread*
sys_arch_current_thread(void)
{
  struct sys_arch_thread* t;
  sys_prot_t old_level;
  ker_thread_id_t id;


  // find out our VDK thread identifier
   id = ker_get_current_thread();

   //LWIP_ASSERT("sys_arch_current_thread: get current thread failed", MR_SUCCESS(mr));

  old_level = sys_arch_protect();

  // see whether there is an entry for it in the thread list already
  for (t = thread_list; t != NULL; t = t->next) {
    if (t->id == id)
      break;
  }

  sys_arch_unprotect(old_level);

  // if we are an unknown VDK thread create a new sys_arch_thread for ourself
  if (t == NULL)
    t = new_sys_arch_thread(id, 0, 0);

  return t;
}


//--------------------------------------------------------------------------
struct sys_timeouts*
sys_arch_timeouts(void)
{
  struct sys_arch_thread* t;

  t = sys_arch_current_thread();
  return (struct sys_timeouts*)&t->timeouts;
}

//--------------------------------------------------------------------------
sys_sem_t
sys_sem_new(u8_t count)
{
  ker_sem_id_t sem;

#ifdef SYS_STATS
  lwip_stats.sys.sem.used++;
  if (lwip_stats.sys.sem.used > lwip_stats.sys.sem.max)
    lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
#endif /* SYS_STATS */

  //LWIP_ASSERT("sys_sem_new: sem created", sem != (ADI_TOOLS_IOE_SEM_ID)UINT_MAX);
  sem = ker_get_semaphore(count,UINT_MAX);

  return (sys_sem_t)sem;
}

//--------------------------------------------------------------------------
void
sys_sem_free(sys_sem_t sem)
{
  if (sem != SYS_SEM_NULL) {
#ifdef SYS_STATS
    lwip_stats.sys.sem.used--;
#endif /* SYS_STATS */
	ker_rel_semaphore((ker_sem_id_t)sem);
	//LWIP_ASSERT("sys_sem_free: release semaphore failed", MR_SUCCESS(mr));
  }
}

//--------------------------------------------------------------------------
void
sys_sem_signal(sys_sem_t sem)
{
	int ret;
	ker_post_semaphore((ker_sem_id_t)sem);
    //LWIP_ASSERT("sys_sem_signal: post semaphore failed", MR_SUCCESS(mr));
}

//--------------------------------------------------------------------------
u32_t
sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
{
  unsigned int pend_time, resume_time;
  int lastError;
  u32_t time_spent;
  kernel_results_e res; 
 
  // get the current time
   pend_time = ker_get_systime();

  // wait for the semaphore
	res = (kernel_results_e)ker_pend_semaphore((ker_sem_id_t)sem,timeout);

 	if(res == ker_err_sem_timeout)
    return SYS_ARCH_TIMEOUT;

  	resume_time = ker_get_systime();
    time_spent = resume_time - pend_time;

  return time_spent;
}

//--------------------------------------------------------------------------
sys_mbox_t
sys_mbox_new(void)
{
  struct sys_arch_mbox* m =
          (struct sys_arch_mbox*)calloc(1, sizeof(struct sys_arch_mbox));

  LWIP_ASSERT("sys_mbox_new: new mbox not allocated", m != NULL);

  // create associated VDK semaphore
  m->id  = ker_get_semaphore(0,SYS_MBOX_SIZE);
  //LWIP_ASSERT("sys_mbox_new: sem not created", m->id != (ADI_TOOLS_IOE_SEM_ID)UINT_MAX);

#ifdef SYS_STATS
  lwip_stats.sys.mbox.used++;
  if (lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max)
    lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
#endif /* SYS_STATS */

  return m;
}

//--------------------------------------------------------------------------
void
sys_mbox_free(sys_mbox_t mbox)
{
  struct sys_arch_mbox* m = (struct sys_arch_mbox*)mbox;

  // unfortunately, the following assertion is sometimes false
  //LWIP_ASSERT("sys_mbox_free: mbox empty", m->count == 0);

	ker_rel_semaphore((ker_sem_id_t)m->id);	
	//LWIP_ASSERT("sys_mbox_free: release semaphore failed", MR_SUCCESS(mr));
  
  free(m);

#ifdef SYS_STATS
  lwip_stats.sys.mbox.used--;
#endif /* SYS_STATS */

}

//--------------------------------------------------------------------------
void
sys_mbox_post(sys_mbox_t mbox, void *msg)
{
  sys_prot_t old_level;
  struct sys_arch_mbox* m = (struct sys_arch_mbox*)mbox;

  old_level = sys_arch_protect();

  LWIP_ASSERT("sys_mbox_post: mbox not full", m->count < SYS_MBOX_SIZE);

  m->msgs[m->wndx++] = msg;
  if (m->wndx == SYS_MBOX_SIZE)
    m->wndx = 0;
  m->count += 1;
  	
  ker_post_semaphore((ker_sem_id_t)m->id);

  //LWIP_ASSERT("sys_mbox_post: post semaphore failed", MR_SUCCESS(mr));
  sys_arch_unprotect(old_level);
}

//--------------------------------------------------------------------------
u32_t
sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
{
  u32_t time_taken;
  sys_prot_t old_level;
  struct sys_arch_mbox* m = (struct sys_arch_mbox*)mbox;

  // wait for a message
  time_taken = sys_arch_sem_wait((sys_sem_t)m->id, timeout);

  old_level = sys_arch_protect();

  // if a message arrived return it to the caller
  if (time_taken != SYS_ARCH_TIMEOUT) {
    LWIP_ASSERT("sys_arch_mbox_fetch: mbox not empty after wait", m->count > 0);
    *msg = m->msgs[m->rndx++];
    if (m->rndx == SYS_MBOX_SIZE)
      m->rndx = 0;
    m->count -= 1;
  }

  sys_arch_unprotect(old_level);

  return time_taken;
}

//--------------------------------------------------------------------------
sys_prot_t
sys_arch_protect(void)
{
  ker_disable_scheduler();
 // ker_disable_interrupts(ker_kPriorityLevelAll);
  prot_level += 1;
  return prot_level-1;
}

//--------------------------------------------------------------------------
void
sys_arch_unprotect(sys_prot_t pval)
{
  LWIP_ASSERT("sys_arch_unprotect: previous < current", pval < prot_level);

  while (prot_level > pval) {
    prot_level -= 1;
    ker_enable_scheduler();
	//	ker_enable_interrupts(ker_kPriorityLevelAll);
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -