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

📄 kwaitq.c

📁 Simple Operating Systems (简称SOS)是一个可以运行在X86平台上(包括QEMU
💻 C
字号:
/* Copyright (C) 2004 David Decotigny   This program is free software; you can redistribute it and/or   modify it under the terms of the GNU General Public License   as published by the Free Software Foundation; either version 2   of the License, or (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,   USA. */#include <sos/klibc.h>#include <sos/list.h>#include <sos/assert.h>#include <hwcore/irq.h>#include "kwaitq.h"sos_ret_t sos_kwaitq_init(struct sos_kwaitq *kwq,			  const char *name){  memset(kwq, 0x0, sizeof(struct sos_kwaitq));#ifdef SOS_KWQ_DEBUG  if (! name)    name = "<unknown>";  strzcpy(kwq->name, name, SOS_KWQ_DEBUG_MAX_NAMELEN);#endif  list_init_named(kwq->waiting_list,		  prev_entry_in_kwaitq, next_entry_in_kwaitq);  return SOS_OK;}sos_ret_t sos_kwaitq_dispose(struct sos_kwaitq *kwq){  sos_ui32_t flags;  sos_ret_t retval;  sos_disable_IRQs(flags);  if (list_is_empty_named(kwq->waiting_list,			  prev_entry_in_kwaitq, next_entry_in_kwaitq))    retval = SOS_OK;  else    retval = -SOS_EBUSY;  sos_restore_IRQs(flags);  return retval;}sos_bool_t sos_kwaitq_is_empty(const struct sos_kwaitq *kwq){  sos_ui32_t flags;  sos_ret_t retval;  sos_disable_IRQs(flags);  retval = list_is_empty_named(kwq->waiting_list,			       prev_entry_in_kwaitq, next_entry_in_kwaitq);  sos_restore_IRQs(flags);  return retval;  }sos_ret_t sos_kwaitq_init_entry(struct sos_kwaitq_entry *kwq_entry){  memset(kwq_entry, 0x0, sizeof(struct sos_kwaitq_entry));  kwq_entry->thread = sos_thread_get_current();  return SOS_OK;}/** Internal helper function equivalent to sos_kwaitq_add_entry(), but    without interrupt protection scheme, and explicit priority    ordering */inline static sos_ret_t _kwaitq_add_entry(struct sos_kwaitq *kwq,					  struct sos_kwaitq_entry *kwq_entry){  /* This entry is already added in the kwaitq ! */  SOS_ASSERT_FATAL(NULL == kwq_entry->kwaitq);  /* sos_kwaitq_init_entry() has not been called ?! */  SOS_ASSERT_FATAL(NULL != kwq_entry->thread);  /* (Re-)Initialize wakeup status of the entry */  kwq_entry->wakeup_triggered = FALSE;  kwq_entry->wakeup_status    = SOS_OK;  /* Add the thread in the list */  list_add_tail_named(kwq->waiting_list, kwq_entry,		      prev_entry_in_kwaitq, next_entry_in_kwaitq);  /* Update the list of waitqueues for the thread */  list_add_tail_named(kwq_entry->thread->kwaitq_list, kwq_entry,		      prev_entry_for_thread, next_entry_for_thread);  kwq_entry->kwaitq = kwq;  return SOS_OK;}sos_ret_t sos_kwaitq_add_entry(struct sos_kwaitq *kwq,			       struct sos_kwaitq_entry *kwq_entry){  sos_ui32_t flags;  sos_ret_t retval;  sos_disable_IRQs(flags);  retval = _kwaitq_add_entry(kwq, kwq_entry);  sos_restore_IRQs(flags);  return retval;}/** Internal helper function equivalent to sos_kwaitq_remove_entry(),    but without interrupt protection scheme */inline static sos_ret_t_kwaitq_remove_entry(struct sos_kwaitq *kwq,		     struct sos_kwaitq_entry *kwq_entry){  SOS_ASSERT_FATAL(kwq_entry->kwaitq == kwq);  list_delete_named(kwq->waiting_list, kwq_entry,		    prev_entry_in_kwaitq, next_entry_in_kwaitq);  list_delete_named(kwq_entry->thread->kwaitq_list, kwq_entry,		    prev_entry_for_thread, next_entry_for_thread);  kwq_entry->kwaitq = NULL;  return SOS_OK;}sos_ret_t sos_kwaitq_remove_entry(struct sos_kwaitq *kwq,				  struct sos_kwaitq_entry *kwq_entry){  sos_ui32_t flags;  sos_ret_t retval;  sos_disable_IRQs(flags);  retval = _kwaitq_remove_entry(kwq, kwq_entry);  sos_restore_IRQs(flags);  return retval;}sos_ret_t sos_kwaitq_wait(struct sos_kwaitq *kwq,			  struct sos_time *timeout){  sos_ui32_t flags;  sos_ret_t retval;  struct sos_kwaitq_entry kwq_entry;  sos_kwaitq_init_entry(& kwq_entry);  sos_disable_IRQs(flags);  retval = _kwaitq_add_entry(kwq, & kwq_entry);  /* Wait for wakeup or timeout */  sos_thread_sleep(timeout);  /* Woken up ! */  /* Sleep delay elapsed ? */  if (! kwq_entry.wakeup_triggered)    {      /* Yes (timeout occured, or wakeup on another waitqueue): remove	 the waitq entry by ourselves */      _kwaitq_remove_entry(kwq, & kwq_entry);      retval = -SOS_EINTR;    }  else    {      retval = kwq_entry.wakeup_status;    }    sos_restore_IRQs(flags);  /* We were correctly awoken: position return status */  return retval;}sos_ret_t sos_kwaitq_wakeup(struct sos_kwaitq *kwq,			    unsigned int nb_threads,			    sos_ret_t wakeup_status){  sos_ui32_t flags;  sos_disable_IRQs(flags);  /* Wake up as much threads waiting in waitqueue as possible (up to     nb_threads), scanning the list in FIFO order */  while (! list_is_empty_named(kwq->waiting_list,			       prev_entry_in_kwaitq, next_entry_in_kwaitq))    {      struct sos_kwaitq_entry *kwq_entry	= list_get_head_named(kwq->waiting_list,			      prev_entry_in_kwaitq, next_entry_in_kwaitq);      /* Enough threads woken up ? */      if (nb_threads <= 0)	break;      /*       * Ok: wake up the thread for this entry       */      /* Thread already woken up ? */      if (SOS_THR_RUNNING == sos_thread_get_state(kwq_entry->thread))	{	  /* Yes => Do nothing because WE are that woken-up thread. In	     particular: don't call set_ready() here because this	     would result in an inconsistent configuration (currently	     running thread marked as "waiting for CPU"...). */	  continue;	}      else	{	  /* No => wake it up now. */	  sos_sched_set_ready(kwq_entry->thread);	}      /* Remove this waitq entry */      _kwaitq_remove_entry(kwq, kwq_entry);      kwq_entry->wakeup_triggered = TRUE;      kwq_entry->wakeup_status    = wakeup_status;      /* Next iteration... */      nb_threads --;    }  sos_restore_IRQs(flags);  return SOS_OK;}

⌨️ 快捷键说明

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