source: rtems/cpukit/include/sys/event.h @ b37ef68

5
Last change on this file since b37ef68 was b37ef68, checked in by dab <dab@…>, on 06/28/18 at 17:01:04

Remove potential identifier conflict in the EV_SET macro.

PR43905 pointed out a problem with the EV_SET macro if the passed
struct kevent pointer were specified with an expression with side
effects (e.g., "kevp++"). This was fixed in rS110241, but by using a
local block that defined an internal variable (named "kevp") to get
the pointer value once. This worked, but could cause issues if an
existing variable named "kevp" is in scope. To avoid that issue,
jilles@ pointed out that "C99 compound literals and designated
initializers allow doing this cleanly using a macro". This change
incorporates that suggestion, essentially verbatim from jilles@
comment on PR43905, except retaining the old definition for pre-C99 or
non-STDC (e.g., C++) compilers.

PR: 43905
Submitted by: Jilles Tjoelker (jilles@)
Reported by: Lamont Granquist <lamont@…>
Reviewed by: jmg (no comments), jilles
MFC after: 1 week
Sponsored by: Dell EMC
Differential Revision: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=43905

  • Property mode set to 100644
File size: 12.7 KB
RevLine 
[8cb2882]1/*-
[bf026dd4]2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
[8cb2882]4 * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
[b3bfc242]28 * $FreeBSD: head/sys/sys/event.h 313704 2017-02-13 19:00:09Z ed $
[8cb2882]29 */
30
31#ifndef _SYS_EVENT_H_
32#define _SYS_EVENT_H_
33
[b3bfc242]34#include <sys/_types.h>
35#include <sys/queue.h>
[8cb2882]36
37#define EVFILT_READ             (-1)
38#define EVFILT_WRITE            (-2)
39#define EVFILT_AIO              (-3)    /* attached to aio requests */
40#define EVFILT_VNODE            (-4)    /* attached to vnodes */
41#define EVFILT_PROC             (-5)    /* attached to struct proc */
42#define EVFILT_SIGNAL           (-6)    /* attached to struct proc */
43#define EVFILT_TIMER            (-7)    /* timers */
[8b8d05f]44#define EVFILT_PROCDESC         (-8)    /* attached to process descriptors */
[8cb2882]45#define EVFILT_FS               (-9)    /* filesystem events */
46#define EVFILT_LIO              (-10)   /* attached to lio requests */
47#define EVFILT_USER             (-11)   /* User events */
[8b8d05f]48#define EVFILT_SENDFILE         (-12)   /* attached to sendfile requests */
[b3bfc242]49#define EVFILT_EMPTY            (-13)   /* empty send socket buf */
50#define EVFILT_SYSCOUNT         13
[8cb2882]51
[b37ef68]52#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
53#define EV_SET(kevp_, a, b, c, d, e, f) do {    \
54    *(kevp_) = (struct kevent){                 \
55        .ident = (a),                           \
56        .filter = (b),                          \
57        .flags = (c),                           \
58        .fflags = (d),                          \
59        .data = (e),                            \
60        .udata = (f),                           \
61        .ext[0] = 0,                            \
62        .ext[1] = 0,                            \
63        .ext[2] = 0,                            \
64        .ext[3] = 0,                            \
65    };                                          \
66} while(0)
67#else /* Pre-C99 or not STDC (e.g., C++) */
68/* The definition of the local variable kevp could possibly conflict
69 * with a user-defined value passed in parameters a-f.
70 */
[8cb2882]71#define EV_SET(kevp_, a, b, c, d, e, f) do {    \
72        struct kevent *kevp = (kevp_);          \
73        (kevp)->ident = (a);                    \
74        (kevp)->filter = (b);                   \
75        (kevp)->flags = (c);                    \
76        (kevp)->fflags = (d);                   \
77        (kevp)->data = (e);                     \
78        (kevp)->udata = (f);                    \
[e9b708a]79        (kevp)->ext[0] = 0;                     \
80        (kevp)->ext[1] = 0;                     \
81        (kevp)->ext[2] = 0;                     \
82        (kevp)->ext[3] = 0;                     \
[8cb2882]83} while(0)
[b37ef68]84#endif
[8cb2882]85
86struct kevent {
[b3bfc242]87        __uintptr_t     ident;          /* identifier for this event */
[8cb2882]88        short           filter;         /* filter for event */
[b3bfc242]89        unsigned short  flags;
90        unsigned int    fflags;
[e9b708a]91        __int64_t       data;
[8cb2882]92        void            *udata;         /* opaque user data identifier */
[e9b708a]93        __uint64_t      ext[4];
[8cb2882]94};
95
[57c03363]96#if defined(_WANT_FREEBSD11_KEVENT)
97/* Older structure used in FreeBSD 11.x and older. */
98struct kevent_freebsd11 {
99        __uintptr_t     ident;          /* identifier for this event */
100        short           filter;         /* filter for event */
101        unsigned short  flags;
102        unsigned int    fflags;
103        __intptr_t      data;
104        void            *udata;         /* opaque user data identifier */
105};
106#endif
107
108#if defined(_WANT_KEVENT32) || (defined(_KERNEL) && defined(__LP64__))
109struct kevent32 {
110        uint32_t        ident;          /* identifier for this event */
111        short           filter;         /* filter for event */
112        u_short         flags;
113        u_int           fflags;
114#ifndef __amd64__
115        uint32_t        pad0;
116#endif
117        int32_t         data1, data2;
118        uint32_t        udata;          /* opaque user data identifier */
119#ifndef __amd64__
120        uint32_t        pad1;
121#endif
122        uint32_t        ext64[8];
123};
124
125#ifdef _WANT_FREEBSD11_KEVENT
126struct kevent32_freebsd11 {
127        u_int32_t       ident;          /* identifier for this event */
128        short           filter;         /* filter for event */
129        u_short         flags;
130        u_int           fflags;
131        int32_t         data;
132        u_int32_t       udata;          /* opaque user data identifier */
133};
134#endif
135#endif
136
[8cb2882]137/* actions */
138#define EV_ADD          0x0001          /* add event to kq (implies enable) */
139#define EV_DELETE       0x0002          /* delete event from kq */
140#define EV_ENABLE       0x0004          /* enable event */
141#define EV_DISABLE      0x0008          /* disable event (not reported) */
[8b8d05f]142#define EV_FORCEONESHOT 0x0100          /* enable _ONESHOT and force trigger */
[8cb2882]143
144/* flags */
145#define EV_ONESHOT      0x0010          /* only report one occurrence */
146#define EV_CLEAR        0x0020          /* clear event state after reporting */
147#define EV_RECEIPT      0x0040          /* force EV_ERROR on success, data=0 */
148#define EV_DISPATCH     0x0080          /* disable event after reporting */
149
150#define EV_SYSFLAGS     0xF000          /* reserved by system */
[353506b9]151#define EV_DROP         0x1000          /* note should be dropped */
[8cb2882]152#define EV_FLAG1        0x2000          /* filter-specific flag */
[8b8d05f]153#define EV_FLAG2        0x4000          /* filter-specific flag */
[8cb2882]154
155/* returned values */
156#define EV_EOF          0x8000          /* EOF detected */
157#define EV_ERROR        0x4000          /* error, data contains errno */
158
159 /*
160  * data/hint flags/masks for EVFILT_USER, shared with userspace
161  *
162  * On input, the top two bits of fflags specifies how the lower twenty four
163  * bits should be applied to the stored value of fflags.
164  *
165  * On output, the top two bits will always be set to NOTE_FFNOP and the
166  * remaining twenty four bits will contain the stored fflags value.
167  */
168#define NOTE_FFNOP      0x00000000              /* ignore input fflags */
169#define NOTE_FFAND      0x40000000              /* AND fflags */
170#define NOTE_FFOR       0x80000000              /* OR fflags */
171#define NOTE_FFCOPY     0xc0000000              /* copy fflags */
172#define NOTE_FFCTRLMASK 0xc0000000              /* masks for operations */
173#define NOTE_FFLAGSMASK 0x00ffffff
174
175#define NOTE_TRIGGER    0x01000000              /* Cause the event to be
176                                                   triggered for output. */
177
178/*
179 * data/hint flags for EVFILT_{READ|WRITE}, shared with userspace
180 */
181#define NOTE_LOWAT      0x0001                  /* low water mark */
[8b8d05f]182#define NOTE_FILE_POLL  0x0002                  /* behave like poll() */
[8cb2882]183
184/*
185 * data/hint flags for EVFILT_VNODE, shared with userspace
186 */
187#define NOTE_DELETE     0x0001                  /* vnode was removed */
188#define NOTE_WRITE      0x0002                  /* data contents changed */
189#define NOTE_EXTEND     0x0004                  /* size increased */
190#define NOTE_ATTRIB     0x0008                  /* attributes changed */
191#define NOTE_LINK       0x0010                  /* link count changed */
192#define NOTE_RENAME     0x0020                  /* vnode was renamed */
193#define NOTE_REVOKE     0x0040                  /* vnode access was revoked */
[8b8d05f]194#define NOTE_OPEN       0x0080                  /* vnode was opened */
195#define NOTE_CLOSE      0x0100                  /* file closed, fd did not
196                                                   allowed write */
197#define NOTE_CLOSE_WRITE 0x0200                 /* file closed, fd did allowed
198                                                   write */
199#define NOTE_READ       0x0400                  /* file was read */
[8cb2882]200
201/*
[8b8d05f]202 * data/hint flags for EVFILT_PROC and EVFILT_PROCDESC, shared with userspace
[8cb2882]203 */
204#define NOTE_EXIT       0x80000000              /* process exited */
205#define NOTE_FORK       0x40000000              /* process forked */
206#define NOTE_EXEC       0x20000000              /* process exec'd */
207#define NOTE_PCTRLMASK  0xf0000000              /* mask for hint bits */
208#define NOTE_PDATAMASK  0x000fffff              /* mask for pid */
209
210/* additional flags for EVFILT_PROC */
211#define NOTE_TRACK      0x00000001              /* follow across forks */
212#define NOTE_TRACKERR   0x00000002              /* could not track child */
213#define NOTE_CHILD      0x00000004              /* am a child process */
214
[8b8d05f]215/* additional flags for EVFILT_TIMER */
216#define NOTE_SECONDS            0x00000001      /* data is seconds */
217#define NOTE_MSECONDS           0x00000002      /* data is milliseconds */
218#define NOTE_USECONDS           0x00000004      /* data is microseconds */
219#define NOTE_NSECONDS           0x00000008      /* data is nanoseconds */
[e9b708a]220#define NOTE_ABSTIME            0x00000010      /* timeout is absolute */
[8b8d05f]221
[8cb2882]222struct knote;
223SLIST_HEAD(klist, knote);
224struct kqueue;
[353506b9]225TAILQ_HEAD(kqlist, kqueue);
[8cb2882]226struct knlist {
227        struct  klist   kl_list;
228        void    (*kl_lock)(void *);     /* lock function */
229        void    (*kl_unlock)(void *);
230        void    (*kl_assert_locked)(void *);
231        void    (*kl_assert_unlocked)(void *);
[8b8d05f]232        void    *kl_lockarg;            /* argument passed to lock functions */
233        int     kl_autodestroy;
[8cb2882]234};
235
236
237#ifdef _KERNEL
238
239/*
240 * Flags for knote call
241 */
242#define KNF_LISTLOCKED  0x0001                  /* knlist is locked */
243#define KNF_NOKQLOCK    0x0002                  /* do not keep KQ_LOCK */
244
[f51aec8]245#define KNOTE(list, hint, flags)        knote(list, hint, flags)
[8cb2882]246#define KNOTE_LOCKED(list, hint)        knote(list, hint, KNF_LISTLOCKED)
247#define KNOTE_UNLOCKED(list, hint)      knote(list, hint, 0)
248
249#define KNLIST_EMPTY(list)              SLIST_EMPTY(&(list)->kl_list)
250
251/*
252 * Flag indicating hint is a signal.  Used by EVFILT_SIGNAL, and also
253 * shared by EVFILT_PROC  (all knotes attached to p->p_klist)
254 */
255#define NOTE_SIGNAL     0x08000000
256
257/*
258 * Hint values for the optional f_touch event filter.  If f_touch is not set
259 * to NULL and f_isfd is zero the f_touch filter will be called with the type
260 * argument set to EVENT_REGISTER during a kevent() system call.  It is also
261 * called under the same conditions with the type argument set to EVENT_PROCESS
262 * when the event has been triggered.
263 */
264#define EVENT_REGISTER  1
265#define EVENT_PROCESS   2
266
267struct filterops {
268        int     f_isfd;         /* true if ident == filedescriptor */
269        int     (*f_attach)(struct knote *kn);
270        void    (*f_detach)(struct knote *kn);
271        int     (*f_event)(struct knote *kn, long hint);
272        void    (*f_touch)(struct knote *kn, struct kevent *kev, u_long type);
273};
274
275/*
[45ae4a8]276 * An in-flux knote cannot be dropped from its kq while the kq is
277 * unlocked.  If the KN_SCAN flag is not set, a thread can only set
278 * kn_influx when it is exclusive owner of the knote state, and can
279 * modify kn_status as if it had the KQ lock.  KN_SCAN must not be set
280 * on a knote which is already in flux.
[8cb2882]281 *
282 * kn_sfflags, kn_sdata, and kn_kevent are protected by the knlist lock.
283 */
284struct knote {
285        SLIST_ENTRY(knote)      kn_link;        /* for kq */
286        SLIST_ENTRY(knote)      kn_selnext;     /* for struct selinfo */
287        struct                  knlist *kn_knlist;      /* f_attach populated */
288        TAILQ_ENTRY(knote)      kn_tqe;
289        struct                  kqueue *kn_kq;  /* which queue we are on */
290        struct                  kevent kn_kevent;
[45ae4a8]291        void                    *kn_hook;
292        int                     kn_hookid;
[8cb2882]293        int                     kn_status;      /* protected by kq lock */
294#define KN_ACTIVE       0x01                    /* event has been triggered */
295#define KN_QUEUED       0x02                    /* event is on queue */
296#define KN_DISABLED     0x04                    /* event is disabled */
297#define KN_DETACHED     0x08                    /* knote is detached */
298#define KN_MARKER       0x20                    /* ignore this knote */
299#define KN_KQUEUE       0x40                    /* this knote belongs to a kq */
300#define KN_HASKQLOCK    0x80                    /* for _inevent */
[353506b9]301#define KN_SCAN         0x100                   /* flux set in kqueue_scan() */
[45ae4a8]302        int                     kn_influx;
[8cb2882]303        int                     kn_sfflags;     /* saved filter flags */
[e9b708a]304        int64_t                 kn_sdata;       /* saved data field */
[8cb2882]305        union {
306                struct          file *p_fp;     /* file data pointer */
307                struct          proc *p_proc;   /* proc pointer */
[8b8d05f]308                struct          kaiocb *p_aio;  /* AIO job pointer */
309                struct          aioliojob *p_lio;       /* LIO job pointer */
310                void            *p_v;           /* generic other pointer */
[8cb2882]311        } kn_ptr;
312        struct                  filterops *kn_fop;
313
314#define kn_id           kn_kevent.ident
315#define kn_filter       kn_kevent.filter
316#define kn_flags        kn_kevent.flags
317#define kn_fflags       kn_kevent.fflags
318#define kn_data         kn_kevent.data
319#define kn_fp           kn_ptr.p_fp
320};
321struct kevent_copyops {
322        void    *arg;
323        int     (*k_copyout)(void *arg, struct kevent *kevp, int count);
324        int     (*k_copyin)(void *arg, struct kevent *kevp, int count);
[e9b708a]325        size_t  kevent_size;
[8cb2882]326};
327
328struct thread;
329struct proc;
330struct knlist;
331struct mtx;
[8b8d05f]332struct rwlock;
[8cb2882]333
[45ae4a8]334void    knote(struct knlist *list, long hint, int lockflags);
335void    knote_fork(struct knlist *list, int pid);
336struct knlist *knlist_alloc(struct mtx *lock);
337void    knlist_detach(struct knlist *knl);
338void    knlist_add(struct knlist *knl, struct knote *kn, int islocked);
339void    knlist_remove(struct knlist *knl, struct knote *kn, int islocked);
340int     knlist_empty(struct knlist *knl);
341void    knlist_init(struct knlist *knl, void *lock, void (*kl_lock)(void *),
342            void (*kl_unlock)(void *), void (*kl_assert_locked)(void *),
343            void (*kl_assert_unlocked)(void *));
344void    knlist_init_mtx(struct knlist *knl, struct mtx *lock);
345void    knlist_init_rw_reader(struct knlist *knl, struct rwlock *lock);
346void    knlist_destroy(struct knlist *knl);
347void    knlist_cleardel(struct knlist *knl, struct thread *td,
348            int islocked, int killkn);
[8cb2882]349#define knlist_clear(knl, islocked)                             \
[45ae4a8]350        knlist_cleardel((knl), NULL, (islocked), 0)
[8cb2882]351#define knlist_delete(knl, td, islocked)                        \
[45ae4a8]352        knlist_cleardel((knl), (td), (islocked), 1)
353void    knote_fdclose(struct thread *p, int fd);
354int     kqfd_register(int fd, struct kevent *kev, struct thread *p,
355            int waitok);
356int     kqueue_add_filteropts(int filt, struct filterops *filtops);
357int     kqueue_del_filteropts(int filt);
[8cb2882]358
359#else   /* !_KERNEL */
360
361#include <sys/cdefs.h>
362struct timespec;
363
364__BEGIN_DECLS
365int     kqueue(void);
366int     kevent(int kq, const struct kevent *changelist, int nchanges,
367            struct kevent *eventlist, int nevents,
368            const struct timespec *timeout);
369__END_DECLS
370
371#endif /* !_KERNEL */
372
373#endif /* !_SYS_EVENT_H_ */
Note: See TracBrowser for help on using the repository browser.