ࡱ;   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Root Entry  !"#$%&'()*+,.012356789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrs ®`VTextStarWriter 5.0GT{:t SfxDocumentInfo Mike {1&Mike P|1xMike |1 Info 0 Info 1 Info 2 Info 3 {1&8<44Standard LIBIMBEDDED LIBIMBEDDED TASK,0,1,H32,0,100,1,2368;219016;110;0;218183;14971;226488;0;0SW5HDR.0P|1x!# Internet linkOutline0 #ZSWG, A<  #$%&'()*./01234 XOutdevItemPool 1   )     &'()*+,-./06789:;UVWXYZ[\]c !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstt      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefd 0cg ' @e' @{' @' @ @ @ @ @ @ @+ @A'@]X'(@Gray 10%X' @' @' @ @ @ @ @/ @E @[ @q @ @ @   @   @   @   @    @! @7 @M @c @y @ @ @ @ @( @( @( @)( @?( @U( @k( @( @(  @(! @(" @(# @$$ @%% @&& @1'' @G(( @])) @s;(+ @,, @-- @.. @// @00 @11 @ 22 @# 33 @9 44 @O 55 @e 66 @{ II @ (L @ MM @ NN @ OO @ PP @ QQ@ XVV@; XWW @U XX @k YY @ ZZ @ [[ @ \\ @ ]] @ ^^ @ __ @ `` @ aa @1 bb @G cc @] dd @s ee @ @ X @ ''X**@ X77@ XHH@7 +'Xff @c QQVVX$:Pf| Tj0F\r "8Ndz*@Vl2H^t$:Pf|*@Vl2Hh PEditEngineItemPool 6f0mg* @ @ @!@@dddX<(@`X (G@Starbats7$rKX@' @A' @1' @+'@ XX' @9!' @O' @e' @{?( @' @' @' @' @' @' @%' @+S' @A"' @W' @m$:P}2\r "8NdzNP+'!''Times'd $6DrMdJoeMn0|1XP|1xP|1x7 DrLyHellDrLyHeavenDrLyControlsDrPgJoeM/pDrML DrObSVDr&%E+J@ D%E+JxV4B1Lock<( (+'<( (+'List<( (+'<( (+' DrObSVDr&$ _)c@ ^$ _)cxV4B1wnext<( (+'<( (+'prev<( (+' DrObnSVDr&$Q/+Y@ Q"$Q/+YxV4B1Flags<( (+'<( (+'task *<( (+'<( (+'List<( (+'<( (+' DrXX Controlsgg DrXX56789:;<=>?@ABCDGHK  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFQRSTUj0!'@yX'&@ TimesNewRomanX'@d X' @X'@ X'(!@:. %. XA'2*@ldxdxdxdXXJJ@X4f+P' TimesNewRoman$' '(. . p. @ . . . . . P. . . !. $. `'. 0*. -. /. 2. p5. @8. ;. =. @. 6')(02 y Internet link Internet link@!''StandardStandard@ Text bodyStandard Text body2A'List Text bodyList'CaptionStandardCaption'' '2A'JJIndexStandardIndex'JJ FooterStandardFooter@('JJRGSBX sb Z Standard StarBASICSBX ARSBX AR SBX AR2c%bqqOh+'0 h t 14@zj@@4@5(Mike Mike SW5HDR.0P|1x! Frameformat ZeichenformatTextformatvorlageStandard Text bodyListCaption IndexFooter Internet linkRoot 11 12 13 14Standard  Illustration Table TextDrawingY .Y .Y .Y .q= GeneralGeneraldNC#,###.00#,###.00SystemNC #,##0.00 CCC#,##0.00 CCCNC$#,##0.--;[RED]-$#,##0.-- $#,##0.---$#,##0.--REDNC$ MM/DD/YYYYMM/DD/YYYY def/SystemNC%MM/DD/YYMM/DD/YY def/SystemNC&NNNNMMMM DD, YYYYNNNNMMMM  DD, YYYYSystemNC' MMM D, YYMMM D, YY def/SystemNC. [HH]:MM:SS.00 [HH ]:MM:SS .00NC3MM/DD/YYYY HH:MM:SS MM/DD/YYYY HH :MM:SS  NCK MMM D, YYYYMMM D, YYYY def/SystemNCL MMMM D, YYYYMMMM  D, YYYY def/SystemNCM NN, MMM D, YYNN, MMM D, YY def/SystemNCNNN, MMMM D, YYYYNN, MMMM  D, YYYY def/SystemNCONNNNMMMM D, YYYYNNNNMMMM  D, YYYY def/SystemNCP D. MMM. YYYYD. MMM. YYYYDIN 5008 (EN 28601)NCQ D. MMMM YYYYD. MMMM  YYYYDIN 5008 (EN 28601)NCRMM-DDMM-DDDIN 5008 (EN 28601)NCSYY-MM-DDYY-MM-DDDIN 5008 (EN 28601)NCT YYYY-MM-DDYYYY-MM-DDDIN 5008 (EN 28601)NCUWWWWNCBXoeP<p5 2$99 SAP/=APdddAPddA PAu Prk FooterSYAPddADPN;T2SA @A0SAAP/=APdddAPddZSW5HDR.0P|1xC(569a(Build:5169)(SV569)]D!Address Book Fileaddress! Frameformat ZeichenformatTextformatvorlageStandard Text bodyListCaption IndexFooter Internet linkRoot 11 12 13 14Standard  Illustration Table TextDrawingd b/1 4 5*jK standard.dic soffice.dicZsun.dic@ IgnoreAllListY .Y .Y .Y .6FN/ T?Process Management in LinuxSA A @T iT3(Kernel source (/usr/src/linux) structureT T4 arch/ SAPdddTb;routines that are architecture dependent (i386, mips, s370)SAPdddTCmuch of boot code lives hereSAPdddT'SAPdddT/drivers/SAPdddTa:device drivers of all ilks live here (net, atm, ide, scsi)SAPdddT/ SAPdddT2 fs/ SAPdddTP)file system code (nfs, ext2, msdos, ntfs)SAPdddT'SAPdddT/include/SAPdddTG headers required to build kernelSAPdddTg@traditionally /usr/include/linux -> /usr/src/linux/include/linuxSAPdddT_8 /user/include/asm -> /usr/src/linux/include/asmSAPdddT/ SAPdddT2 init/ SAPdddTW0contains "main.c" and the start_kernel function.SAPdddT( SAPdddT1 ipc/ SAPdddTW0user level semaphore and shared memory support SAPdddT'SAPdddT5kernel/ SAPdddThAscheduling, process creation, interrupt handling, signal handlingSAPdddT'SAPdddT2 lib/ SAPdddTjCkernel implementation of stdlib functions (memcpy, strlen, sprintf)SAPdddT( SAPdddT*mm/SAPdddT8memory managementSAPdddT/ SAPdddT1 net/ SAPdddTg@network protocol stacks (ipv4, ipv6, native atm, appletalk, ipx)SAPdddTJ#actual drivers live in drivers/net SAPdddT  T3(For perusing the Linux source code use: T  TO http://lxr.linux.no/A/8 http://lxr.linux.no/T T;search by identifierSAPdddT8free text search SAPdddT8hypertext linkingSAPdddT'SAPdddTNProcess management structuresS&APdddA T'SAPdddT](struct task_struct defines the linux pcbSAPdddA8 %(T1S&APdddA  To281 struct task_struct {SLAPdddACourierAd A  T]282 /*SLAPdddACourierAd A  T@283 * offsets of these are hardcoded elsewhere - touch with careSLAPdddACourierAd A  T]284 */SLAPdddACourierAd A  TG285 volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */SLAPdddACourierAd A  TB286 unsigned long flags; /* per process flags, defined below */SLAPdddACourierAd A  Tv287 int sigpending;SAPdddA8 A8d A8CourierT<288 mm_segment_t addr_limit; /* thread address space:SLAPdddACourierAd A  T[289 SLAPdddACourierAd A  TWSLAPdddACourierAd A  T?Process statesS&APdddA TWSLAPdddACourierAd A  T/#define TASK_RUNNING 0 SAPdddA8 A8d A8CourierTs#define TASK_INTERRUPTIBLE 1SLAPdddACourierAd A  Tu#define TASK_UNINTERRUPTIBLE 2SLAPdddACourierAd A  Tl#define TASK_ZOMBIE 4SLAPdddACourierAd A  Tm#define TASK_STOPPED 8SLAPdddACourierAd A  TWSLAPdddACourierAd A  TWSLAPdddACourierAd A  T\5Running in execution or wishing to be in execution.SAPdddTQ*Interruptible in interruptible_sleep_on()SAPdddTEUninterruptible in sleep_on()SAPdddTZ3Zombie exited but parent has not yet issued wait()SAPdddTBStopped victim of SIG_STOPSAPdddT'SAPdddT`9Note discrepancy between comment above and actual definesSAPdddT'SAPdddTDProcess descriptorsS&APdddA T1S&APdddA TkEach process (including kernel level threads created with pthread_create()) has a unique process descriptorS7APdddA A@. TBS7APdddA A@. TGThe system name for a process is the address of its process descriptor.S7APdddA A@. A8  A8  GTLSAAPdddA  A A@. TTThe variable/macro current can be used to obtain the address of the running process.SAAPdddA  A A@. A8 TLSAAPdddA  A A@. T@The user name for a process is the pid field of the task struct.SAAPdddA  A A@. A8 #A8 '@TLSAAPdddA  A A@. T336 pid_t pid;SgAPdddpACourierAd A  A A@. T337 pid_t pgrp;SgAPdddpACourierAd A  A A@. T338 pid_t tty_old_pgrp;SgAPdddpACourierAd A  A A@. T339 pid_t session;SgAPdddpACourierAd A  A A@. T340 pid_t tgid;SgAPdddpACourierAd A  A A@. TrSgAPdddACourierAd A  A A@. TM SAAPdddA  A A@. T8S-APdddA@. T8S-APdddA@. TrProcess descriptor managmentSKAPdddA PA  A A@. TLSAAPdddA  A A@. TgEach process descriptor is SAAPdddA  A A@. T\page aligned andSAAPdddpA  A A@. Ta2 pages (8KB) in sizeSAAPdddpA  A A@. TLSAAPdddA  A A@. TeIt is actually defined asSAAPdddA  A A@. TrSgAPdddACourierAd A  A A@. T-508 # define INIT_TASK_SIZE 2048*sizeof(long)SgAPdddpACourierAd A  A A@. T| 509 #endifSgAPdddpACourierAd A  A A@. T510 union task_union {SgAPdddpACourierAd A  A A@. T511 struct task_struct task;SgAPdddpACourierAd A  A A@. T5512 unsigned long stack[INIT_TASK_SIZE/sizeof(long)];SgAPdddpACourierAd A  A A@. Tx513 };SgAPdddpACourierAd A  A A@. TrSgAPdddpACourierAd A  A A@. TOKernel mode stack lives at the top of the task_struct space and grows downward.SAAPdddA  A A@. TGAt each entry to kernel, the ESP reg is set to point to current + 8192SAAPdddA  A A@. TLSAAPdddA  A A@. T:This structure makes it easy to retreive current from esp.SAAPdddA  A A@. A8 )0A8 6:T:It also makes current work transparently on UP and SMP .. SAAPdddA  A A@. A8 Tjno more need for current arraySAAPdddpA  A A@. TrSgAPdddACourierAd A  A A@. Tt5 SgAPdddpACourierAd A  A A@. T66 static inline struct task_struct * get_current(void)SgAPdddpACourierAd A  A A@. Tu7 {SgAPdddpACourierAd A  A A@. T8 struct task_struct *current;SgAPdddpACourierAd A  A A@. T;9 __asm__("andl %%esp,%0; ":"=r" (current) : "" (~8191UL));SgAPdddpACourierAd A  A A@. T10 return current;SgAPdddpACourierAd A  A A@. Tv11 }SgAPdddpACourierAd A  A A@. Tu12 SgAPdddpACourierAd A  A A@. T 13 #define current get_current()SgAPdddpACourierAd A  A A@. Tu14 SgAPdddpACourierAd A  A A@. T"15 #endif /* !(_I386_CURRENT_H) */SgAPdddpACourierAd A  A A@. TrSgAPdddACourierAd A  A A@. TLSAAPdddA  A A@. TmPotential problem: SAAPdddA  A A@. A8 TLSAAPdddA  A A@. T\Stack grows downSAAPdddpA  A A@. T5What if it reaches the data part of the task_struct??SAAPdddpA  A A@. TLSAAPdddA  A A@. TLSAAPdddA  A A@. TYTo provide for efficient allocation of task structures a small stack of free ones is keptSKAPdddA PA  A A@. TLSAAPdddA  A A@. Tx229 /*SgAPdddACourierAd A  A A@. T1230 * Task structure and kernel stack allocation.SgAPdddACourierAd A  A A@. Tx231 */SgAPdddACourierAd A  A A@. T0232 static struct task_struct *task_struct_head;SgAPdddACourierAd A  A A@. T'233 static unsigned int nr_task_struct;SgAPdddACourierAd A  A A@. Tv234 SgAPdddACourierAd A  A A@. T235 #ifdef CONFIG_CPU_32SgAPdddACourierAd A  A A@. T236 #define EXTRA_TASK_STRUCT 4SgAPdddACourierAd A  A A@. T{ 237 #elseSgAPdddACourierAd A  A A@. T238 #define EXTRA_TASK_STRUCT 0SgAPdddACourierAd A  A A@. T| 239 #endifSgAPdddACourierAd A  A A@. Tv240 SgAPdddACourierAd A  A A@. T/241 struct task_struct *alloc_task_struct(void)SgAPdddACourierAd A  A A@. Tw242 {SgAPdddACourierAd A  A A@. T243 struct task_struct *tsk;SgAPdddACourierAd A  A A@. Tv244 SgAPdddACourierAd A  A A@. T245 if (EXTRA_TASK_STRUCT)SgAPdddACourierAd A  A A@. T246 tsk = task_struct_head;SgAPdddACourierAd A  A A@. Tz247 elseSgAPdddACourierAd A  A A@. T248 tsk = NULL;SgAPdddACourierAd A  A A@. Tv249 SgAPdddACourierAd A  A A@. T250 if (tsk) {SgAPdddACourierAd A  A A@. T'251 task_struct_head = tsk->next_task;SgAPdddACourierAd A  A A@. T252 nr_task_struct -= 1;SgAPdddACourierAd A  A A@. T| 253 } elseSgAPdddACourierAd A  A A@. T"254 tsk = ll_alloc_task_struct();SgAPdddACourierAd A  A A@. Tu255SgAPdddACourierAd A  A A@. T261 if (tsk) {SgAPdddACourierAd A  A A@. T262 char *p = (char *)tsk;SgAPdddACourierAd A  A A@. T5263 memzero(p+KERNEL_STACK_SIZE, KERNEL_STACK_SIZE);SgAPdddACourierAd A  A A@. Tw264 }SgAPdddACourierAd A  A A@. T| 265 #endifSgAPdddACourierAd A  A A@. T266 return tsk;SgAPdddACourierAd A  A A@. TLSAAPdddA  A A@. T8S-APdddA@. TVSKAPdddA PA  A A@. T<Process (task) structure is maintained using circular listsSAAPdddA  A A@. TLSAAPdddA  A A@. TeThe task_struct contains:SAAPdddA  A A@. TLSAAPdddA  A A@. Ti320 */SXAPdddACourierA  A A@. T321 struct list_head run_list;SXAPdddACourierA  A A@. T322 unsigned long sleep_time;SXAPdddACourierA  A A@. Tg323 SXAPdddACourierA  A A@. T.324 struct task_struct *next_task, *prev_task;SXAPdddACourierA  A A@. T 325 struct mm_struct *active_mm;SXAPdddACourierA  A A@. T!326 struct list_head local_pages;SXAPdddACourierA  A A@. TcSXAPdddACourierA  A A@. T4The following macro can search through all processesSAAPdddA  A A@. TLSAAPdddA  A A@. T870 #define for_each_task(p) \SXAPdddACourierA  A A@. T>871 for (p = &init_task ; (p = p->next_task) != &init_task ; )SXAPdddACourierA  A A@. TcSXAPdddACourierA  A A@. T?Other macros in sched.h set and unset parent child relationshipSAAPdddA  A A@. TLSAAPdddA  A A@. T859 #define SET_LINKS(p) do { \SXAPdddACourierA  A A@. T"860 (p)->next_task = &init_task; \SXAPdddACourierA  A A@. T,861 (p)->prev_task = init_task.prev_task; \SXAPdddACourierA  A A@. T,862 init_task.prev_task->next_task = (p); \SXAPdddACourierA  A A@. T!863 init_task.prev_task = (p); \SXAPdddACourierA  A A@. T~864 (p)->p_ysptr = NULL; \SXAPdddACourierA  A A@. T8865 if (((p)->p_osptr = (p)->p_pptr->p_cptr) != NULL) \SXAPdddACourierA  A A@. T!866 (p)->p_osptr->p_ysptr = p; \SXAPdddACourierA  A A@. T867 (p)->p_pptr->p_cptr = p; \SXAPdddACourierA  A A@. Tr868 } while (0)SXAPdddACourierA  A A@. Te86SXAPdddACourierA  A A@. TcSXAPdddACourierA  A A@. TfProcess sleepingSKAPdddA PA  A A@. TLSAAPdddA  A A@. TDDepends upon a couple of data structures used in process management:SAAPdddA  A A@. o+: SA  PA PT8S-APdddA@. T>First is the wait_queue_head_t (used in your semaphore driver)SAAPdddA  A A@. TLSAAPdddA  A A@. T77 struct __wait_queue_head {SXAPdddACourierA  A A@. Tu78 wq_lock_t lock;SXAPdddACourierA  A A@. T79 struct list_head task_list;SXAPdddACourierA  A A@. Th84 };SXAPdddACourierA  A A@. T685 typedef struct __wait_queue_head wait_queue_head_t;SXAPdddACourierA  A A@. TLSAAPdddA  A A@. TMNext is the wait_queue element (not to be confused with the wait queue head) SAAPdddA  A A@. TLSAAPdddA  A A@. Tf30 SXAPdddACourierA  A A@. T31 struct __wait_queue {SXAPdddACourierA  A A@. o+: SA  PA PTy32 unsigned int flags;SXAPdddACourierA  A A@. Te33SXAPdddACourierA  A A@. T34 struct task_struct * task;SXAPdddACourierA  A A@. T35 struct list_head task_list;SXAPdddACourierA  A A@. Ty36 #if WAITQUEUE_DEBUGSXAPdddACourierA  A A@. Ts37 long __magic;SXAPdddACourierA  A A@. Ts38 long __waker;SXAPdddACourierA  A A@. Tl 39 #endifSXAPdddACourierA  A A@. Th40 };SXAPdddACourierA  A A@. T,41 typedef struct __wait_queue wait_queue_t;SXAPdddACourierA  A A@. Tf42 SXAPdddACourierA  A A@. TLSAAPdddA  A A@. T}1These fellows reference the generic list element SAAPdddA  A A@. TwSAAPdddA  A A@. o+: SA  PA PTx18 struct list_head {SXAPdddACourierA  A A@. T"19 struct list_head *next, *prev;SXAPdddACourierA  A A@. Th20 };SXAPdddACourierA  A A@. TLSAAPdddA  A A@. TLSAAPdddA  A A@. TVSKAPdddA PA  A A@. TRThe routine looks simple, but depends on an seemingly endless set of nested macrosSAAPdddA  A A@. TLSAAPdddA  A A@. T5805 void interruptible_sleep_on(wait_queue_head_t *q)SXAPdddACourierA  A A@. Th806 {SXAPdddACourierA  A A@. Tt807 SLEEP_ON_VARSXAPdddACourierA  A A@. Tg808 SXAPdddACourierA  A A@. T)809 current->state = TASK_INTERRUPTIBLE;SXAPdddACourierA  A A@. Tg810 SXAPdddACourierA  A A@. Tu811 SLEEP_ON_HEADSXAPdddACourierA  A A@. Ts812 schedule();SXAPdddACourierA  A A@. Tu813 SLEEP_ON_TAILSXAPdddACourierA  A A@. Th814 }SXAPdddACourierA  A A@. Tn815SDAPdddACourierA@. A8A8 T8S-APdddA@. TZ"Define and init local variables.. S-APdddA@. T@Note that the actual queue element is a local (stack) variable S-APdddA@. A8 .6A8 6>T8S-APdddA@. T790 #define SLEEP_ON_VAR \SgAPdddACourierAd A  A A@. T.791 unsigned long flags; \SgAPdddACourierAd A  A A@. T.792 wait_queue_t wait; \SgAPdddACourierAd A  A A@. T+793 init_waitqueue_entry(&wait, current);SgAPdddACourierAd A  A A@. T794 SgAPdddACourierAd A  A A@. A8d TLSAAPdddA  A A@. TEInitialization just saves current in the task structure pointer fieldSAAPdddA  A A@. T8S-APdddA@. T,169 static inline void init_waitqueue_entry(SXAPdddACourierA  A A@. T) wait_queue_t *q, struct task_struct *p)SXAPdddACourierA  A A@. Th170 {SXAPdddACourierA  A A@. Tn :SDAPdddACourierA@. A8A8 Tv175 q->flags = 0;SXAPdddACourierA  A A@. Tu176 q->task = p;SXAPdddACourierA  A A@. Tf :SXAPdddACourierA  A A@. Th180 }SXAPdddACourierA  A A@. TLSAAPdddA  A A@. T9Next we lock and add the wait queue structure to the listSAAPdddA  A A@. TLSAAPdddA  A A@. T~795 #define SLEEP_ON_HEAD \SXAPdddACourierA  A A@. T6796 wq_write_lock_irqsave(&q->lock,flags); \SXAPdddACourierA  A A@. T6797 __add_wait_queue(q, &wait); \SXAPdddACourierA  A A@. T798 wq_write_unlock(&q->lock);SXAPdddACourierA  A A@. TLSAAPdddA  A A@. TLSAAPdddA  A A@. TbBefore getting into the mechanics of insertion its useful to see how the queue head is initializedSKAPdddA PA  A A@. TLSAAPdddA  A A@. T@155 static inline void init_waitqueue_head(wait_queue_head_t *q)SXAPdddACourierA  A A@. Th156 {SXAPdddACourierA  A A@. Tz157 #if WAITQUEUE_DEBUGSXAPdddACourierA  A A@. Tn 158 if (!q)SXAPdddACourierA  A A@. Tp 159 WQ_BUG();SXAPdddACourierA  A A@. Tm 160 #endifSXAPdddACourierA  A A@. T)161 q->lock = WAITQUEUE_RW_LOCK_UNLOCKED;SXAPdddACourierA  A A@. T"162 INIT_LIST_HEAD(&q->task_list);SXAPdddACourierA  A A@. Tz163 #if WAITQUEUE_DEBUGSXAPdddACourierA  A A@. T#164 q->__magic = (long)&q->__magic;SXAPdddACourierA  A A@. T-165 q->__creator = (long)current_text_addr();SXAPdddACourierA  A A@. Tm 166 #endifSXAPdddACourierA  A A@. Th167 }SXAPdddACourierA  A A@. TLSAAPdddA  A A@. TdNote that this function depends on the generic list initializer.. which points both links to itself.SAAPdddA  A A@. TLSAAPdddA  A A@. T%27 #define INIT_LIST_HEAD(ptr) do { \SXAPdddACourierA  A A@. T.28 (ptr)->next = (ptr); (ptr)->prev = (ptr); \SXAPdddACourierA  A A@. Tq29 } while (0)SXAPdddACourierA  A A@. Tf30 SXAPdddACourierA  A A@. TcSXAPdddACourierA  A A@. TmSbAPdddA PACourierA  A A@. TRThe implementation of add wait queue just calls the generic list processor passingSAAPdddA  A A@. TYit pointers to the task list structures of the wait queue head and new waitqueue element.SAAPdddA  A A@. TLSAAPdddA  A A@. TS193 static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)SXAPdddACourierA  A A@. Th194 {SXAPdddACourierA  A A@. Tn :SDAPdddACourierA@. A8A8 T1203 list_add(&new->task_list, &head->task_list);SXAPdddACourierA  A A@. Th204 }SXAPdddACourierA  A A@. Tg205 SXAPdddACourierA  A A@. TcSXAPdddACourierA  A A@. Tn=Which in turn extracts the current next pointer from the headS&APdddA T1S&APdddA TT55 static __inline__ void list_add(struct list_head *new, struct list_head *head)S=APdddACourierA TL56 {S=APdddACourierA Tn&57 __list_add(new, head, head->next);S=APdddACourierA TL58 }S=APdddACourierA THS=APdddACourierA THS=APdddACourierA Tc2And then calls the complete generic list inserter.S&APdddA T1S&APdddA T<37 static __inline__ void __list_add(struct list_head * new,S=APdddACourierA Tc38 struct list_head * prev,S=APdddACourierA Tc39 struct list_head * next)S=APdddACourierA TL40 {S=APdddACourierA T]41 next->prev = new;S=APdddACourierA T]42 new->next = next;S=APdddACourierA T]43 new->prev = prev;S=APdddACourierA T]44 prev->next = new;S=APdddACourierA TL45 }S=APdddACourierA T1S&APdddA T1S&APdddA Tc785 #define SLEEP_ON_TAIL \S=APdddACourierA T=786 wq_write_lock_irq(&q->lock); \S=APdddACourierA T=787 __remove_wait_queue(q, &wait); \S=APdddACourierA Tw/788 wq_write_unlock_irqrestore(&q->lock,flags);S=APdddACourierA TL789 S=APdddACourierA THS=APdddACourierA TRSGAPdddA PACourierA Tk*Recall the body of interruptible sleep on:S6APdddAA TAS6APdddAA Tu811 SLEEP_ON_HEADSXAPdddACourierA  A A@. Ts812 schedule();SXAPdddACourierA  A A@. Tu813 SLEEP_ON_TAILSXAPdddACourierA  A A@. TcSXAPdddACourierA  A A@. TTSchedule selects another process to begin execution and performs the context switch.S6APdddAA T:SLEEP_ON_TAIL is not executed until after the wakeup call.S6APdddAA A8 $*A8 *:TRSGAPdddACourierA  A T~785 #define SLEEP_ON_TAIL \SXAPdddACourierA  A A@. T=786 wq_write_lock_irq(&q->lock); \SXAPdddACourierA  A A@. T=787 __remove_wait_queue(q, &wait); \SXAPdddACourierA  A A@. T/788 wq_write_unlock_irqrestore(&q->lock,flags);SXAPdddACourierA  A A@. TcSXAPdddACourierA  A A@. T@Remove wait queue unlinks the wait_queue element from the queue.S6APdddAA TAS6APdddAA TC223 static inline void __remove_wait_queue(wait_queue_head_t *head,S=APdddACourierA T^224 wait_queue_t *old)S=APdddACourierA TM225 {S=APdddACourierA TI:S=APdddACourierA Th 231 list_del(&old->task_list);S=APdddACourierA TM232 }S=APdddACourierA TI S=APdddACourierA TAS6APdddAA Tg&list_del works analogously to list addS6APdddAA TAS6APdddAA T;92 static __inline__ void list_del(struct list_head *entry)S=APdddACourierA TL93 {S=APdddACourierA Tq)94 __list_del(entry->prev, entry->next);S=APdddACourierA TL95 }S=APdddACourierA THS=APdddACourierA T=80 static __inline__ void __list_del(struct list_head * prev,S=APdddACourierA Tc81 struct list_head * next)S=APdddACourierA TL82 {S=APdddACourierA T^83 next->prev = prev;S=APdddACourierA T^84 prev->next = next;S=APdddACourierA TL85 }S=APdddACourierA TAS6APdddAA T^Waking processes upS@APdddA PAA TAS6APdddAA TX599 #define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE, 1)S=APdddACourierA TAS6APdddAA T~=Get the lock and then call wakeup_common to do the real work.S6APdddAA TAS6APdddAA TC725 void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr)S=APdddACourierA TM726 {S=APdddACourierA TU 727 if (q) {S=APdddACourierA Tb728 unsigned long flags;S=APdddACourierA Tt,729 wq_read_lock_irqsave(&q->lock, flags);S=APdddACourierA To'730 __wake_up_common(q, mode, nr, 0);S=APdddACourierA Ty1731 wq_read_unlock_irqrestore(&q->lock, flags);S=APdddACourierA TN732 }S=APdddACourierA TM733 }S=APdddACourierA TAS6APdddAA Tr1Run through the entire list waking all processes.S6APdddAA TAS6APdddAA Tu701 static inline void __wake_up_common (wait_queue_head_t *q, unsigned int mode, int nr_exclusive, const int sync)SAPdddA8SA8SCourierA8TuA8TuCourierTM703 {S=APdddACourierA Tc704 struct list_head *tmp;S=APdddACourierA Td705 struct task_struct *p;S=APdddACourierA TM706 S=APdddACourierA Tc707 CHECK_MAGIC_WQHEAD(q);S=APdddACourierA To'708 WQ_CHECK_LIST_HEAD(&q->task_list);S=APdddACourierA TL709 S=APdddACourierA To'710 list_for_each(tmp,&q->task_list) {S=APdddACourierA Ta711 unsigned int state;S=APdddACourierA TM712 wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list);S=APdddACourierA TL713 S=APdddACourierA Ti!714 CHECK_MAGIC(curr->__magic);S=APdddACourierA T]715 p = curr->task;S=APdddACourierA T_716 state = p->state;S=APdddACourierA Ta717 if (state & mode) {S=APdddACourierA Tc718 WQ_NOTE_WAKER(curr);S=APdddACourierA Tn&719 if (try_to_wake_up(p, sync) && S=APdddACourierA T@ (curr->flags&WQ_FLAG_EXCLUSIVE) && !-- nr_exclusive)S=APdddACourierA TU 720 break;S=APdddACourierA TO721 }S=APdddACourierA TN722 }S=APdddACourierA TM723 }S=APdddACourierA THS=APdddACourierA THS=APdddACourierA TRSGAPdddA PACourierA T]The list_entry macroSAPdddA8A8TI S=APdddACourierA TO137 /**S=APdddACourierA Tx0138 * list_entry - get the struct for this entryS=APdddACourierA Ty1139 * @ptr: the &struct list_head pointer.S=APdddACourierA T>140 * @type: the type of the struct this is embedded in.S=APdddACourierA TA141 * @member: the name of the list_struct within the struct.S=APdddACourierA TN142 */S=APdddACourierA Ts+143 #define list_entry(ptr, type, member) \S=APdddACourierA TC144 ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))S=APdddACourierA TL145 S=APdddACourierA TO146 /**S=APdddACourierA THS=APdddACourierA Tgis used to extract a pointer to the wait_queue_t structure from a pointer to the list_head it containsS=APdddACourierA A8gTHS=APdddACourierA Tr* list_entry(tmp, wait_queue_t, task_list);S=APdddACourierA THS=APdddACourierA Tg Expands to S=APdddACourierA A8 TI S=APdddACourierA Tj" ((wait_queue_t*)((char *)(tmp) - S=APdddACourierA T|4 (unsigned long)(&((wait_queue_t *)0)->task_list))S=APdddACourierA TAS6APdddAA TKS@APdddA PAA Ty'The key elements of try_to_wakeup are: S9APdddA TimesNewRomanA8'T'SAPdddTv- setting the tasks state to TASK_RUNNING and SAPdddA8(A8(T`9making sure the task struct is on the is on the runqueue.SAPdddT\5processes are deleted from the runqueue in schedule()SAPdddTAS6APdddAA TP336 static inline int try_to_wake_up(struct task_struct * p, int synchronous)S=APdddACourierA TM337 {S=APdddACourierA Ta338 unsigned long flags;S=APdddACourierA T]339 int success = 0;S=APdddACourierA TL340 S=APdddACourierA TN341 /*S=APdddACourierA TC342 * We want the common case fall through straight, thus the goto.S=APdddACourierA TN343 */S=APdddACourierA Tv.344 spin_lock_irqsave(&runqueue_lock, flags);S=APdddACourierA Te345 p->state = TASK_RUNNING;S=APdddACourierA Te346 if (task_on_runqueue(p))S=APdddACourierA TW347 goto out;S=APdddACourierA T`348 add_to_runqueue(p);S=APdddACourierA TN349 if (!synchronous || !(p->cpus_allowed & (1 << smp_processor_id())))S=APdddACourierA Ta350 reschedule_idle(p);S=APdddACourierA TY351 success = 1;S=APdddACourierA TP352 out:S=APdddACourierA T{3353 spin_unlock_irqrestore(&runqueue_lock, flags);S=APdddACourierA T\354 return success;S=APdddACourierA TM355 }S=APdddACourierA TL356 S=APdddACourierA THS=APdddACourierA T5The runqueue list_head is embedded in the task_structSCAPdddA TimesNewRomanA TAS6APdddAA Tf321 struct list_head run_list;S=APdddACourierA Te322 unsigned long sleep_time;S=APdddACourierA TL323 S=APdddACourierA Tv.324 struct task_struct *next_task, *prev_task;S=APdddACourierA Th 325 struct mm_struct *active_mm;S=APdddACourierA THS=APdddACourierA THS=APdddACourierA TRSGAPdddA PACourierA T>The runqueue head and associated locks are declared in sched.cSCAPdddA TimesNewRomanA TNSCAPdddA TimesNewRomanA T=89 struct task_struct * init_tasks[NR_CPUS] = {&init_task, };S=APdddACourierA TJ80S=APdddACourierA TM81 /*S=APdddACourierA T=82 * The tasklist_lock protects the linked list of processes.S=APdddACourierA TL83 *S=APdddACourierA T;84 * The runqueue_lock locks the parts that actually accessS=APdddACourierA T>85 * and change the run-queues, and have to be interrupt-safe.S=APdddACourierA TL86 *S=APdddACourierA TA87 * If both locks are to be concurrently held, the runqueue_lockS=APdddACourierA Tl$88 * nests inside the tasklist_lock.S=APdddACourierA TL89 *S=APdddACourierA Ty190 * task->alloc_lock nests inside tasklist_lock.S=APdddACourierA TM91 */S=APdddACourierA TT92 spinlock_t runqueue_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; /* inner */S=APdddACourierA TC93 rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED; SAPdddA8CA8CCourierTU /* outer */S=APdddACourierA TK94 S=APdddACourierA Tk#95 static LIST_HEAD(runqueue_head);S=APdddACourierA THS=APdddACourierA THS=APdddACourierA TAS6APdddAA TAS6APdddAA TAS6APdddAA TAS6APdddAA TAS6APdddAA TAS6APdddAA THS=APdddACourierA THS=APdddACourierA THS=APdddACourierA THS=APdddACourierA THS=APdddACourierA JLexmark Optra T614 Laser PrinterLOPT614 PostScript`Tl`Tld,,lp -d lwnlwnLOPT614PageSize:LetterDuplex:NoneDuplexer:FalseInputSlot:AutoSelectMediaType:NoneTray2:FalseTray3:FalseTray4:FalseTray5:FalseMPFeeder:TrueFeeder:FalseImageEnhance:TrueResolution:600dpiSmoothing:False7 U5׍5!V88/p?Д/=U&2PJU&x0?.B&B& B#& B0& B=& BJ& E# BW& E*! Bd& E*! Bq& E*!  B~ & E#  B & E*!  B & E*!  B & E#  B & E*! B& E*! B& E# B& E*! B& E*! B& E*! B& E*! B & E# B& E*! B'& E*! B4& E# BA& E*! BN& E# B[& E# Bh& E*! Bu& E*! B& E# B& E*! B & E#  B!& E# !B"& E*! "B#& E*! #B$& E# $B%& E*! %B&& E*! &B'& 'B)& (B*& )B+& *B+,& +B8-& E# ,BE.& E# -BR/& E# .,U6&(& F@& J>/=U&2pU&x0?3B& E# /B &0B#& 1B0& E# 2B=&E#3BE&E#4B&E#5B&E#6B&E#7B=&E#8B&E#9B &E#:Bw &E#;B5 &E#<B &E#=B &>B &?B& E# @@B&E#AAB^&E#BBB&E#CCB&E#DDB&EEBV&E#FFB& E# GGB!& E# HHB.& E# IIB;& E# JJBH& E# KKBU& E# LLBb& E# MMBo& E# NNB|&OOB&PPB&E$QRB & E$ RSB!& E$ STB"& E$ TUB#& E$ UVB$&E$VWB%& E$ WXB '&E$XYB(&EB&E $=?Bc &E $>@BG &E $?AB+ & @BB8 & ACBE &E#BEB &E#CFB&E#DGB&E#EHB&E#FIB&GJB& HKB& ILB&E#JMB&E#KNBc&E#LOBG&E#MPB+&E#NQB&E#ORB&E#PSB&E#QTB&E#RUB& SVB& TWB&E#UXB &E#VYB!&E#WZBe"&E#X[BI#&E#Y\B-$&Z],U6&(& F@& Ъ%6/=U&2p ]U&x0?'B&[^B& \_B& ]`B&E $^aB&E $_bB&E $`cB&E $adB& beB& cfB&dgB &E $ehBp &E $fiBT &E $gjB8 &E $hkB &E $ilB& jmB & knB&loB&mpB&nqB&orB&psB&qtBr&ruBV& svBc& twBp& uxB}&vyBa&wzBE&x{B)&y|B &z}B&{~B&|B&}B &~B!&Be"&BI#& ,U6&(& F@& л%u/=U&2P nU&x0?+B&B&B,&B&B & B& B$&B&B&B &B &B &B| &B` &BD&B(&B>& BK&Ba&BR&B6&B&B&B&B&B&B&Br&BV&B&B&B&B &B!&B"&Bv#&BZ$&B"&&B'&B'&B(&B)&B*&,U6&(& F@& +%Դ/=U&2p U&x0?B&B& B&B&B&B&B&Be&BI&B-&B &B &B &B &B & B &B&Bv&BZ& Bg&BK&B/&B& ,U6&(& F@& s%/=U&2P &U&x0?&B& B & B& E# B'& E# B4& E# BA& E# BN& B[&B# &B &B &B &B &B &B{&B_&BC&B'&B &B&B&B&B&Bc&BG&B+&B&B&B&B& B& B&B&B &B!&Be"&BI#&B-$&,U6&(& F@& %2/=U&2pºU&x0?"B&B& B& B&B&B&B&B&Br&BV&B: &B &B &B &B &B &B&BZ&B>&B"&B&B& B& B&  B&  B&  B& B& B& B&B&B& B& B& ,U6&(& F@& lZRoot Entry ®`VCompObj<Ole persist elements" SfxDocumentInfo uStarBASIC BasicManager2 4SfxWindowsCDrawingLayer SwNumRulesfSfxStyleSheetsStandard-jSummaryInformation( /0SwPageStyleSheets$4StarWriterDocument&