summaryrefslogtreecommitdiffstats
path: root/lib/workqueue.h
blob: c42d6c46087ecffeba3306c894e7c4d7b21fa4a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
 * Quagga Work Queues.
 *
 * Copyright (C) 2005 Sun Microsystems, Inc.
 *
 * This file is part of Quagga.
 *
 * Quagga 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, or (at your option) any
 * later version.
 *
 * Quagga 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 Quagga; see the file COPYING.  If not, write to the Free
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 */

#ifndef _QUAGGA_WORK_QUEUE_H
#define _QUAGGA_WORK_QUEUE_H

#include "misc.h"

/* Hold time for the initial schedule of a queue run, in  millisec */
enum { WORK_QUEUE_DEFAULT_HOLD = 50 } ;

/* action value, for use by item processor and item error handlers */
typedef enum
{
  WQ_SUCCESS = 0,
  WQ_ERROR,             /* Error, run error handler if provided */
  WQ_RETRY_NOW,         /* retry immediately */
  WQ_RETRY_LATER,       /* retry later, cease processing work queue */
  WQ_REQUEUE,		/* requeue item, continue processing work queue */
  WQ_QUEUE_BLOCKED,	/* Queue cant be processed at this time.
                         * Similar to WQ_RETRY_LATER, but doesn't penalise
                         * the particular item.. */
} wq_item_status;

enum { wq_args_size_max  = 24 } ;      /* maximum size of union wq_args */

union wq_args
{
  void* data ;
  char  bytes[wq_args_size_max] ;      /* empty space                  `*/
} ;

#define WQ_ARGS_SIZE_OK(s) CONFIRM(sizeof(struct s) <= wq_args_size_max)

/* A single work queue item, unsurprisingly */
typedef struct work_queue_item* work_queue_item ;
struct work_queue_item
{
  union wq_args args ;                  /* cast as required             */

  struct work_queue_item* next ;        /* the queue itself             */
  struct work_queue_item* prev ;

  unsigned short ran;			/* # of times item has been run */
} ;

/* work_queue_item structures are malloced.  That guarantees maximum alignment.
 * To guarantee maximum alignment for "struct args", it must be first item !
 *
 * (The typedef is required to stop Eclipse (3.4.2 with CDT 5.0) whining
 *  about first argument of offsetof().)
 */
typedef struct work_queue_item work_queue_item_t ;
CONFIRM(offsetof(work_queue_item_t, args) == 0) ;
                                        /* so guaranteed max alignment  */

#define WQ_UNPLUGGED	(1 << 0) /* available for draining */

typedef struct work_queue* work_queue ;

typedef wq_item_status wq_workfunc(work_queue, work_queue_item);
typedef void           wq_errorfunc(work_queue, work_queue_item);
typedef void           wq_del_item_data(work_queue, work_queue_item);
typedef void           wq_completion_func(work_queue);

struct work_queue
{
  /* Everything but the specification struct is private
   * the following may be read
   */
  struct thread_master *master;       /* thread master */
  struct thread *thread;              /* thread, if one is active */
  char *name;                         /* work queue name */

  /* Specification for this work queue.
   * Public, must be set before use by caller. May be modified at will.
   */
  struct {
    /* optional opaque user data, global to the queue.                  */
    void *data;

    /* work function to process items with:
     * First argument is the workqueue queue.
     * Second argument is the item data
     */
    wq_workfunc* workfunc ;

    /* error handling function -- optional                              */
    wq_errorfunc* errorfunc ;

    /* callback to delete user specific item data -- optional           */
    wq_del_item_data* del_item_data ;

    /* completion callback, called when queue is emptied -- optional    */
    wq_completion_func* completion_func ;

    /* max number of retries to make for item that errors */
    unsigned int max_retries;

    unsigned int hold;	/* hold time for first run, in ms */
  } spec;

  /* remaining fields should be opaque to users */
  work_queue_item head ;              /* queue item list        */
  work_queue_item tail ;
  unsigned      list_count ;

  unsigned long runs;                 /* runs count             */

  struct {
    unsigned int best;
    unsigned int granularity;
    unsigned long total;
  } cycles;	/* cycle counts */

  /* private state */
  u_int16_t flags;		/* user set flag */
};

/* User API */

/* create a new work queue, of given name.
 * user must fill in the spec of the returned work queue before adding
 * anything to it
 */
extern struct work_queue *work_queue_new (struct thread_master *,
                                          const char *);
/* destroy work queue */
extern void work_queue_free (struct work_queue *);

/* Add the supplied data as an item onto the workqueue */
Inline void work_queue_add (struct work_queue *, void *);

extern void* work_queue_item_add(struct work_queue* wq) ;
Inline void* work_queue_item_args(work_queue_item item) ;

/* plug the queue, ie prevent it from being drained / processed */
extern void work_queue_plug (struct work_queue *wq);
/* unplug the queue, allow it to be drained again */
extern void work_queue_unplug (struct work_queue *wq);

/* Helpers, exported for thread.c and command.c */
extern int work_queue_run (struct thread *);

/* Reporting commands                                           */
extern cmd_table workqueue_cmd_table ;

/*==============================================================================
 * The Inline functions
 */

Inline void work_queue_add (struct work_queue* wq, void* data)
{
  union wq_args* args = work_queue_item_add(wq) ;
  args->data = data ;
}

/* Return pointer to the args area in the given work queue item         */
Inline void*
work_queue_item_args(work_queue_item item)
{
  return &item->args ;
} ;

#endif /* _QUAGGA_WORK_QUEUE_H */