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

📄 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,			  sos_kwaitq_ordering_t ordering){  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  kwq->ordering = ordering;  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 */inline static sos_ret_t_kwaitq_add_entry(struct sos_kwaitq *kwq,		  struct sos_kwaitq_entry *kwq_entry,		  sos_sched_priority_t prio){  struct sos_kwaitq_entry *next_entry = NULL, *entry;  int nb_entries;  /* 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;  /* Insert this entry in the kwaitq waiting list */  switch (kwq->ordering)    {    case SOS_KWQ_ORDER_FIFO:      /* Insertion in the list in FIFO order */      {	/* Add the thread in the list */	list_add_tail_named(kwq->waiting_list, kwq_entry,			    prev_entry_in_kwaitq, next_entry_in_kwaitq);      }      break;          case SOS_KWQ_ORDER_PRIO:      /* Priority-driven insertion in the list */      {	/* Look for the place where to insert the thread in the queue (we	   want to order them in order of increasing priorities) */	list_foreach_forward_named(kwq->waiting_list, entry, nb_entries,				   prev_entry_in_kwaitq, next_entry_in_kwaitq)	  {	    /* Does the thread we want to insert have higher priority than	       the given thread in the queue ? */	    if (SOS_SCHED_PRIO_CMP(prio,				   sos_thread_get_priority(entry->thread))		> 0)	      {		/* Yes: we insert before this given thread */		next_entry = entry;		break;	      }	  }	/* Actually insert the entry in the list */	if (next_entry != NULL)	  {	    list_insert_before_named(kwq->waiting_list, kwq_entry, next_entry,				     prev_entry_in_kwaitq,				     next_entry_in_kwaitq);	  }	else	  {	    /* The thread we want to insert has less priority than any	       other in the list */	    list_add_tail_named(kwq->waiting_list, kwq_entry,				prev_entry_in_kwaitq, next_entry_in_kwaitq);	  }      }      break;    default:      SOS_FATAL_ERROR("Invalid kwq ordering %d !\n", kwq->ordering);      break;    }  /* 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_thread_get_priority(kwq_entry->thread));  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,		             sos_thread_get_priority(kwq_entry.thread));  /* 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/decreasing priority order     (depends on the kwaitq ordering) */  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;}/* Internal function (callback for thread subsystem) */sos_ret_t sos_kwaitq_change_priority(struct sos_kwaitq *kwq,				     struct sos_kwaitq_entry *kwq_entry,				     sos_sched_priority_t priority){  /* Reorder the waiting list */  _kwaitq_remove_entry(kwq, kwq_entry);  _kwaitq_add_entry(kwq, kwq_entry, priority);  return SOS_OK;}

⌨️ 快捷键说明

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