home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / linux / sunrpc / sched.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  9.5 KB  |  306 lines

  1. /*
  2.  * linux/include/linux/sunrpc/sched.h
  3.  *
  4.  * Scheduling primitives for kernel Sun RPC.
  5.  *
  6.  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
  7.  */
  8.  
  9. #ifndef _LINUX_SUNRPC_SCHED_H_
  10. #define _LINUX_SUNRPC_SCHED_H_
  11.  
  12. #include <linux/timer.h>
  13. #include <linux/sunrpc/types.h>
  14. #include <linux/spinlock.h>
  15. #include <linux/wait.h>
  16. #include <linux/workqueue.h>
  17. #include <linux/sunrpc/xdr.h>
  18.  
  19. /*
  20.  * This is the actual RPC procedure call info.
  21.  */
  22. struct rpc_procinfo;
  23. struct rpc_message {
  24.     struct rpc_procinfo *    rpc_proc;    /* Procedure information */
  25.     void *            rpc_argp;    /* Arguments */
  26.     void *            rpc_resp;    /* Result */
  27.     struct rpc_cred *    rpc_cred;    /* Credentials */
  28. };
  29.  
  30. struct rpc_call_ops;
  31. struct rpc_wait_queue;
  32. struct rpc_wait {
  33.     struct list_head    list;        /* wait queue links */
  34.     struct list_head    links;        /* Links to related tasks */
  35.     struct rpc_wait_queue *    rpc_waitq;    /* RPC wait queue we're on */
  36. };
  37.  
  38. /*
  39.  * This is the RPC task struct
  40.  */
  41. struct rpc_task {
  42. #ifdef RPC_DEBUG
  43.     unsigned long        tk_magic;    /* 0xf00baa */
  44. #endif
  45.     atomic_t        tk_count;    /* Reference count */
  46.     struct list_head    tk_task;    /* global list of tasks */
  47.     struct rpc_clnt *    tk_client;    /* RPC client */
  48.     struct rpc_rqst *    tk_rqstp;    /* RPC request */
  49.     int            tk_status;    /* result of last operation */
  50.  
  51.     /*
  52.      * RPC call state
  53.      */
  54.     struct rpc_message    tk_msg;        /* RPC call info */
  55.     __u8            tk_garb_retry;
  56.     __u8            tk_cred_retry;
  57.  
  58.     unsigned long        tk_cookie;    /* Cookie for batching tasks */
  59.  
  60.     /*
  61.      * timeout_fn   to be executed by timer bottom half
  62.      * callback    to be executed after waking up
  63.      * action    next procedure for async tasks
  64.      * tk_ops    caller callbacks
  65.      */
  66.     void            (*tk_timeout_fn)(struct rpc_task *);
  67.     void            (*tk_callback)(struct rpc_task *);
  68.     void            (*tk_action)(struct rpc_task *);
  69.     const struct rpc_call_ops *tk_ops;
  70.     void *            tk_calldata;
  71.  
  72.     /*
  73.      * tk_timer is used for async processing by the RPC scheduling
  74.      * primitives. You should not access this directly unless
  75.      * you have a pathological interest in kernel oopses.
  76.      */
  77.     struct timer_list    tk_timer;    /* kernel timer */
  78.     unsigned long        tk_timeout;    /* timeout for rpc_sleep() */
  79.     unsigned short        tk_flags;    /* misc flags */
  80.     unsigned char        tk_priority : 2;/* Task priority */
  81.     unsigned long        tk_runstate;    /* Task run status */
  82.     struct workqueue_struct    *tk_workqueue;    /* Normally rpciod, but could
  83.                          * be any workqueue
  84.                          */
  85.     union {
  86.         struct work_struct    tk_work;    /* Async task work queue */
  87.         struct rpc_wait        tk_wait;    /* RPC wait */
  88.     } u;
  89.  
  90.     unsigned short        tk_timeouts;    /* maj timeouts */
  91.     size_t            tk_bytes_sent;    /* total bytes sent */
  92.     unsigned long        tk_start;    /* RPC task init timestamp */
  93.     long            tk_rtt;        /* round-trip time (jiffies) */
  94.  
  95. #ifdef RPC_DEBUG
  96.     unsigned short        tk_pid;        /* debugging aid */
  97. #endif
  98. };
  99. #define tk_auth            tk_client->cl_auth
  100. #define tk_xprt            tk_client->cl_xprt
  101.  
  102. /* support walking a list of tasks on a wait queue */
  103. #define    task_for_each(task, pos, head) \
  104.     list_for_each(pos, head) \
  105.         if ((task=list_entry(pos, struct rpc_task, u.tk_wait.list)),1)
  106.  
  107. #define    task_for_first(task, head) \
  108.     if (!list_empty(head) &&  \
  109.         ((task=list_entry((head)->next, struct rpc_task, u.tk_wait.list)),1))
  110.  
  111. /* .. and walking list of all tasks */
  112. #define    alltask_for_each(task, pos, head) \
  113.     list_for_each(pos, head) \
  114.         if ((task=list_entry(pos, struct rpc_task, tk_task)),1)
  115.  
  116. typedef void            (*rpc_action)(struct rpc_task *);
  117.  
  118. struct rpc_call_ops {
  119.     void (*rpc_call_prepare)(struct rpc_task *, void *);
  120.     void (*rpc_call_done)(struct rpc_task *, void *);
  121.     void (*rpc_release)(void *);
  122. };
  123.  
  124.  
  125. /*
  126.  * RPC task flags
  127.  */
  128. #define RPC_TASK_ASYNC        0x0001        /* is an async task */
  129. #define RPC_TASK_SWAPPER    0x0002        /* is swapping in/out */
  130. #define RPC_TASK_CHILD        0x0008        /* is child of other task */
  131. #define RPC_CALL_MAJORSEEN    0x0020        /* major timeout seen */
  132. #define RPC_TASK_ROOTCREDS    0x0040        /* force root creds */
  133. #define RPC_TASK_DYNAMIC    0x0080        /* task was kmalloc'ed */
  134. #define RPC_TASK_KILLED        0x0100        /* task was killed */
  135. #define RPC_TASK_SOFT        0x0200        /* Use soft timeouts */
  136. #define RPC_TASK_NOINTR        0x0400        /* uninterruptible task */
  137.  
  138. #define RPC_IS_ASYNC(t)        ((t)->tk_flags & RPC_TASK_ASYNC)
  139. #define RPC_IS_CHILD(t)        ((t)->tk_flags & RPC_TASK_CHILD)
  140. #define RPC_IS_SWAPPER(t)    ((t)->tk_flags & RPC_TASK_SWAPPER)
  141. #define RPC_DO_ROOTOVERRIDE(t)    ((t)->tk_flags & RPC_TASK_ROOTCREDS)
  142. #define RPC_ASSASSINATED(t)    ((t)->tk_flags & RPC_TASK_KILLED)
  143. #define RPC_DO_CALLBACK(t)    ((t)->tk_callback != NULL)
  144. #define RPC_IS_SOFT(t)        ((t)->tk_flags & RPC_TASK_SOFT)
  145. #define RPC_TASK_UNINTERRUPTIBLE(t) ((t)->tk_flags & RPC_TASK_NOINTR)
  146.  
  147. #define RPC_TASK_RUNNING    0
  148. #define RPC_TASK_QUEUED        1
  149. #define RPC_TASK_WAKEUP        2
  150. #define RPC_TASK_HAS_TIMER    3
  151. #define RPC_TASK_ACTIVE        4
  152.  
  153. #define RPC_IS_RUNNING(t)    (test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
  154. #define rpc_set_running(t)    (set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
  155. #define rpc_test_and_set_running(t) \
  156.                 (test_and_set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
  157. #define rpc_clear_running(t)    \
  158.     do { \
  159.         smp_mb__before_clear_bit(); \
  160.         clear_bit(RPC_TASK_RUNNING, &(t)->tk_runstate); \
  161.         smp_mb__after_clear_bit(); \
  162.     } while (0)
  163.  
  164. #define RPC_IS_QUEUED(t)    (test_bit(RPC_TASK_QUEUED, &(t)->tk_runstate))
  165. #define rpc_set_queued(t)    (set_bit(RPC_TASK_QUEUED, &(t)->tk_runstate))
  166. #define rpc_clear_queued(t)    \
  167.     do { \
  168.         smp_mb__before_clear_bit(); \
  169.         clear_bit(RPC_TASK_QUEUED, &(t)->tk_runstate); \
  170.         smp_mb__after_clear_bit(); \
  171.     } while (0)
  172.  
  173. #define rpc_start_wakeup(t) \
  174.     (test_and_set_bit(RPC_TASK_WAKEUP, &(t)->tk_runstate) == 0)
  175. #define rpc_finish_wakeup(t) \
  176.     do { \
  177.         smp_mb__before_clear_bit(); \
  178.         clear_bit(RPC_TASK_WAKEUP, &(t)->tk_runstate); \
  179.         smp_mb__after_clear_bit(); \
  180.     } while (0)
  181.  
  182. #define RPC_IS_ACTIVATED(t)    (test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate))
  183. #define rpc_set_active(t)    (set_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate))
  184. #define rpc_clear_active(t)    \
  185.     do { \
  186.         smp_mb__before_clear_bit(); \
  187.         clear_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate); \
  188.         smp_mb__after_clear_bit(); \
  189.     } while(0)
  190.  
  191. /*
  192.  * Task priorities.
  193.  * Note: if you change these, you must also change
  194.  * the task initialization definitions below.
  195.  */
  196. #define RPC_PRIORITY_LOW    0
  197. #define RPC_PRIORITY_NORMAL    1
  198. #define RPC_PRIORITY_HIGH    2
  199. #define RPC_NR_PRIORITY        (RPC_PRIORITY_HIGH+1)
  200.  
  201. /*
  202.  * RPC synchronization objects
  203.  */
  204. struct rpc_wait_queue {
  205.     spinlock_t        lock;
  206.     struct list_head    tasks[RPC_NR_PRIORITY];    /* task queue for each priority level */
  207.     unsigned long        cookie;            /* cookie of last task serviced */
  208.     unsigned char        maxpriority;        /* maximum priority (0 if queue is not a priority queue) */
  209.     unsigned char        priority;        /* current priority */
  210.     unsigned char        count;            /* # task groups remaining serviced so far */
  211.     unsigned char        nr;            /* # tasks remaining for cookie */
  212.     unsigned short        qlen;            /* total # tasks waiting in queue */
  213. #ifdef RPC_DEBUG
  214.     const char *        name;
  215. #endif
  216. };
  217.  
  218. /*
  219.  * This is the # requests to send consecutively
  220.  * from a single cookie.  The aim is to improve
  221.  * performance of NFS operations such as read/write.
  222.  */
  223. #define RPC_BATCH_COUNT            16
  224.  
  225. #ifndef RPC_DEBUG
  226. # define RPC_WAITQ_INIT(var,qname) { \
  227.         .lock = SPIN_LOCK_UNLOCKED, \
  228.         .tasks = { \
  229.             [0] = LIST_HEAD_INIT(var.tasks[0]), \
  230.             [1] = LIST_HEAD_INIT(var.tasks[1]), \
  231.             [2] = LIST_HEAD_INIT(var.tasks[2]), \
  232.         }, \
  233.     }
  234. #else
  235. # define RPC_WAITQ_INIT(var,qname) { \
  236.         .lock = SPIN_LOCK_UNLOCKED, \
  237.         .tasks = { \
  238.             [0] = LIST_HEAD_INIT(var.tasks[0]), \
  239.             [1] = LIST_HEAD_INIT(var.tasks[1]), \
  240.             [2] = LIST_HEAD_INIT(var.tasks[2]), \
  241.         }, \
  242.         .name = qname, \
  243.     }
  244. #endif
  245. # define RPC_WAITQ(var,qname)      struct rpc_wait_queue var = RPC_WAITQ_INIT(var,qname)
  246.  
  247. #define RPC_IS_PRIORITY(q)        ((q)->maxpriority > 0)
  248.  
  249. /*
  250.  * Function prototypes
  251.  */
  252. struct rpc_task *rpc_new_task(struct rpc_clnt *, int flags,
  253.                 const struct rpc_call_ops *ops, void *data);
  254. struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
  255.                 const struct rpc_call_ops *ops, void *data);
  256. struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent);
  257. void        rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt,
  258.                 int flags, const struct rpc_call_ops *ops,
  259.                 void *data);
  260. void        rpc_release_task(struct rpc_task *);
  261. void        rpc_exit_task(struct rpc_task *);
  262. void        rpc_killall_tasks(struct rpc_clnt *);
  263. int        rpc_execute(struct rpc_task *);
  264. void        rpc_run_child(struct rpc_task *parent, struct rpc_task *child,
  265.                     rpc_action action);
  266. void        rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
  267. void        rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
  268. void        rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
  269.                     rpc_action action, rpc_action timer);
  270. void        rpc_wake_up_task(struct rpc_task *);
  271. void        rpc_wake_up(struct rpc_wait_queue *);
  272. struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
  273. void        rpc_wake_up_status(struct rpc_wait_queue *, int);
  274. void        rpc_delay(struct rpc_task *, unsigned long);
  275. void *        rpc_malloc(struct rpc_task *, size_t);
  276. void        rpc_free(struct rpc_task *);
  277. int        rpciod_up(void);
  278. void        rpciod_down(void);
  279. int        __rpc_wait_for_completion_task(struct rpc_task *task, int (*)(void *));
  280. #ifdef RPC_DEBUG
  281. void        rpc_show_tasks(void);
  282. #endif
  283. int        rpc_init_mempool(void);
  284. void        rpc_destroy_mempool(void);
  285. extern struct workqueue_struct *rpciod_workqueue;
  286.  
  287. static inline void rpc_exit(struct rpc_task *task, int status)
  288. {
  289.     task->tk_status = status;
  290.     task->tk_action = rpc_exit_task;
  291. }
  292.  
  293. static inline int rpc_wait_for_completion_task(struct rpc_task *task)
  294. {
  295.     return __rpc_wait_for_completion_task(task, NULL);
  296. }
  297.  
  298. #ifdef RPC_DEBUG
  299. static inline const char * rpc_qname(struct rpc_wait_queue *q)
  300. {
  301.     return ((q && q->name) ? q->name : "unknown");
  302. }
  303. #endif
  304.  
  305. #endif /* _LINUX_SUNRPC_SCHED_H_ */
  306.