Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-29 09:17:37

0001 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
0002 /*
0003  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
0004  *                         University Research and Technology
0005  *                         Corporation.  All rights reserved.
0006  * Copyright (c) 2004-2006 The University of Tennessee and The University
0007  *                         of Tennessee Research Foundation.  All rights
0008  *                         reserved.
0009  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
0010  *                         University of Stuttgart.  All rights reserved.
0011  * Copyright (c) 2004-2005 The Regents of the University of California.
0012  *                         All rights reserved.
0013  * Copyright (c) 2015-2020 Intel, Inc.  All rights reserved.
0014  * Copyright (c) 2020      IBM Corporation.  All rights reserved.
0015  * Copyright (c) 2021-2025 Nanook Consulting  All rights reserved.
0016  * $COPYRIGHT$
0017  *
0018  * Additional copyrights may follow
0019  *
0020  * $HEADER$
0021  */
0022 
0023 #ifndef PMIX_EVENT_H
0024 #define PMIX_EVENT_H
0025 
0026 #include "src/include/pmix_config.h"
0027 #include "src/include/pmix_types.h"
0028 #include <event.h>
0029 
0030 #include "pmix_common.h"
0031 #include "src/class/pmix_list.h"
0032 #include "src/mca/bfrops/bfrops_types.h"
0033 #include "src/threads/pmix_threads.h"
0034 #include "src/util/pmix_output.h"
0035 
0036 BEGIN_C_DECLS
0037 
0038 #define PMIX_EVENT_ORDER_NONE          0x00
0039 #define PMIX_EVENT_ORDER_FIRST         0x01
0040 #define PMIX_EVENT_ORDER_LAST          0x02
0041 #define PMIX_EVENT_ORDER_BEFORE        0x04
0042 #define PMIX_EVENT_ORDER_AFTER         0x08
0043 #define PMIX_EVENT_ORDER_PREPEND       0x10
0044 #define PMIX_EVENT_ORDER_APPEND        0x20
0045 #define PMIX_EVENT_ORDER_FIRST_OVERALL 0x40
0046 #define PMIX_EVENT_ORDER_LAST_OVERALL  0x80
0047 
0048 /* define an internal attribute for marking that the
0049  * server processed an event before passing it up
0050  * to its host in case it comes back down - avoids
0051  * infinite loop */
0052 #define PMIX_SERVER_INTERNAL_NOTIFY "pmix.srvr.internal.notify"
0053 
0054 /* define a struct for tracking registration ranges */
0055 typedef struct {
0056     pmix_data_range_t range;
0057     pmix_proc_t *procs;
0058     size_t nprocs;
0059 } pmix_range_trkr_t;
0060 
0061 #define PMIX_RANGE_TRKR_STATIC_INIT     \
0062 {                                       \
0063     .range = PMIX_RANGE_UNDEF,          \
0064     .procs = NULL,                      \
0065     .nprocs = 0                         \
0066 }
0067 
0068 
0069 /* define a common struct for tracking event handlers */
0070 typedef struct {
0071     pmix_list_item_t super;
0072     char *name;
0073     size_t index;
0074     uint8_t precedence;
0075     bool oneshot;
0076     char *locator;
0077     pmix_proc_t source; // who generated this event
0078     /* When registering for events, callers can specify
0079      * the range of sources from which they are willing
0080      * to receive notifications - e.g., for callers to
0081      * define different handlers for events coming from
0082      * the RM vs those coming from their peers. We use
0083      * the rng field to track these values upon registration.
0084      */
0085     pmix_range_trkr_t rng;
0086     /* For registration, we use the affected field to track
0087      * the range of procs that, if affected by the event,
0088      * should cause the handler to be called (subject, of
0089      * course, to any rng constraints).
0090      */
0091     pmix_proc_t *affected;
0092     size_t naffected;
0093     pmix_notification_fn_t evhdlr;
0094     void *cbobject;
0095     pmix_status_t *codes;
0096     size_t ncodes;
0097 } pmix_event_hdlr_t;
0098 PMIX_CLASS_DECLARATION(pmix_event_hdlr_t);
0099 
0100 #define PMIX_EVENT_HDLR_STATIC_INIT         \
0101 {                                           \
0102     .super = PMIX_LIST_ITEM_STATIC_INIT,    \
0103     .name = NULL,                           \
0104     .index = SIZE_MAX,                      \
0105     .precedence = UINT8_MAX,                \
0106     .locator = NULL,                        \
0107     .source = PMIX_PROC_STATIC_INIT,        \
0108     .rng = PMIX_RANGE_TRKR_STATIC_INIT,     \
0109     .affected - NULL,                       \
0110     .naffected = 0,                         \
0111     .evhdlr = NULL,                         \
0112     .cbobject = NULL,                       \
0113     .codes = NULL,                          \
0114     .ncodes = 0                             \
0115 }
0116 
0117 /* define an object for tracking status codes we are actively
0118  * registered to receive */
0119 typedef struct {
0120     pmix_list_item_t super;
0121     pmix_status_t code;
0122     size_t nregs;
0123     void *peer; // (pmix_peer_t *)
0124 } pmix_active_code_t;
0125 PMIX_CLASS_DECLARATION(pmix_active_code_t);
0126 
0127 /* define an object for housing the different lists of events
0128  * we have registered so we can easily scan them in precedent
0129  * order when we get an event */
0130 typedef struct {
0131     pmix_object_t super;
0132     size_t nhdlrs;
0133     pmix_event_hdlr_t *first;
0134     pmix_event_hdlr_t *last;
0135     pmix_list_t actives;
0136     pmix_list_t single_events;
0137     pmix_list_t multi_events;
0138     pmix_list_t default_events;
0139 } pmix_events_t;
0140 PMIX_CLASS_DECLARATION(pmix_events_t);
0141 
0142 #define PMIX_EVENTS_STATIC_INIT                     \
0143 {                                                   \
0144     .super = PMIX_OBJ_STATIC_INIT(pmix_object_t),   \
0145     .nhdlrs = 0,                                    \
0146     .first = NULL,                                  \
0147     .last = NULL,                                   \
0148     .actives = PMIX_LIST_STATIC_INIT,               \
0149     .single_events = PMIX_LIST_STATIC_INIT,         \
0150     .multi_events = PMIX_LIST_STATIC_INIT,          \
0151     .default_events = PMIX_LIST_STATIC_INIT         \
0152 }
0153 
0154 /* define an object for chaining event notifications thru
0155  * the local state machine. Each registered event handler
0156  * that asked to be notified for a given code is given a
0157  * chance to "see" the reported event, starting with
0158  * single-code handlers, then multi-code handlers, and
0159  * finally default handlers. This object provides a
0160  * means for us to relay the event across that chain
0161  */
0162 typedef struct pmix_event_chain_t {
0163     pmix_list_item_t super;
0164     pmix_status_t status;
0165     pmix_event_t ev;
0166     bool timer_active;
0167     bool nondefault;
0168     bool endchain;
0169     bool cached;
0170     pmix_proc_t source;
0171     pmix_data_range_t range;
0172     /* When generating events, callers can specify
0173      * the range of targets to receive notifications.
0174      */
0175     pmix_proc_t *targets;
0176     size_t ntargets;
0177     /* the processes that we affected by the event */
0178     pmix_proc_t *affected;
0179     size_t naffected;
0180     /* any info provided by the event generator */
0181     pmix_info_t *info;
0182     size_t ninfo;
0183     size_t nallocated;
0184     pmix_status_t interim_status;
0185     pmix_info_t *results;
0186     size_t nresults;
0187     pmix_info_t *interim;
0188     size_t ninterim;
0189     pmix_event_hdlr_t *evhdlr;
0190     pmix_op_cbfunc_t opcbfunc;
0191     void *cbdata;
0192     pmix_op_cbfunc_t final_cbfunc;
0193     void *final_cbdata;
0194 } pmix_event_chain_t;
0195 PMIX_CLASS_DECLARATION(pmix_event_chain_t);
0196 
0197 typedef struct {
0198     pmix_object_t super;
0199     volatile bool active;
0200     pmix_event_t ev;
0201     pmix_lock_t lock;
0202     pmix_status_t status;
0203     size_t index;
0204     bool firstoverall;
0205     bool enviro;
0206     pmix_list_t *list;
0207     pmix_event_hdlr_t *hdlr;
0208     void *cd;
0209     pmix_status_t *codes;
0210     size_t ncodes;
0211     pmix_info_t *info;
0212     size_t ninfo;
0213     pmix_proc_t *affected;
0214     size_t naffected;
0215     pmix_notification_fn_t evhdlr;
0216     pmix_hdlr_reg_cbfunc_t evregcbfn;
0217     void *cbdata;
0218 } pmix_rshift_caddy_t;
0219 PMIX_CLASS_DECLARATION(pmix_rshift_caddy_t);
0220 
0221 /* prepare a chain for processing by cycling across provided
0222  * info structs and translating those supported by the event
0223  * system into the chain object*/
0224 PMIX_EXPORT pmix_status_t pmix_prep_event_chain(pmix_event_chain_t *chain, const pmix_info_t *info,
0225                                                 size_t ninfo, bool xfer);
0226 
0227 /* invoke the error handler that is registered against the given
0228  * status, passing it the provided info on the procs that were
0229  * affected, plus any additional info provided by the server */
0230 PMIX_EXPORT void pmix_invoke_local_event_hdlr(pmix_event_chain_t *chain);
0231 
0232 PMIX_EXPORT bool pmix_notify_check_range(pmix_range_trkr_t *rng, const pmix_proc_t *proc);
0233 
0234 PMIX_EXPORT bool pmix_notify_check_affected(pmix_proc_t *interested, size_t ninterested,
0235                                             pmix_proc_t *affected, size_t naffected);
0236 
0237 PMIX_EXPORT pmix_status_t pmix_deregister_event_hdlr(size_t event_hdlr_ref,
0238                                                      pmix_buffer_t *msg);
0239 
0240 /* invoke the server event notification handler */
0241 PMIX_EXPORT pmix_status_t pmix_server_notify_client_of_event(pmix_status_t status,
0242                                                              const pmix_proc_t *source,
0243                                                              pmix_data_range_t range,
0244                                                              const pmix_info_t info[], size_t ninfo,
0245                                                              pmix_op_cbfunc_t cbfunc, void *cbdata);
0246 PMIX_EXPORT pmix_status_t pmix_notify_server_of_event(pmix_status_t status, const pmix_proc_t *source,
0247                                                       pmix_data_range_t range, const pmix_info_t info[],
0248                                                       size_t ninfo, pmix_op_cbfunc_t cbfunc, void *cbdata,
0249                                                       bool dolocal);
0250 
0251 PMIX_EXPORT void pmix_event_timeout_cb(int sd, short args, void *cbdata);
0252 
0253 PMIX_EXPORT void pmix_internal_notify_event(int sd, short args, void *cbdata);
0254 
0255 PMIX_EXPORT void pmix_internal_reg_event_hdlr(int sd, short args, void *cbdata);
0256 
0257 #define PMIX_REPORT_EVENT(e, p, r, f)                                                          \
0258     do {                                                                                       \
0259         pmix_event_chain_t *ch, *cp;                                                           \
0260         size_t _n;                                                                             \
0261                                                                                                \
0262         ch = NULL;                                                                             \
0263         /* see if we already have this event cached */                                         \
0264         PMIX_LIST_FOREACH (cp, &pmix_globals.cached_events, pmix_event_chain_t) {              \
0265             if (cp->status == (e)) {                                                           \
0266                 ch = cp;                                                                       \
0267                 break;                                                                         \
0268             }                                                                                  \
0269         }                                                                                      \
0270         if (NULL == ch) {                                                                      \
0271             /* nope - need to add it */                                                        \
0272             ch = PMIX_NEW(pmix_event_chain_t);                                                 \
0273             ch->status = (e);                                                                  \
0274             ch->range = (r);                                                                   \
0275             PMIX_LOAD_PROCID(&ch->source, (p)->nptr->nspace, (p)->info->pname.rank);           \
0276             PMIX_PROC_CREATE(ch->affected, 1);                                                 \
0277             ch->naffected = 1;                                                                 \
0278             PMIX_LOAD_PROCID(ch->affected, (p)->nptr->nspace, (p)->info->pname.rank);          \
0279             /* if this is lost-connection-to-server, then we let it go to */                   \
0280             /* the default event handler - otherwise, we don't */                              \
0281             if (PMIX_ERR_LOST_CONNECTION != (e) && PMIX_ERR_UNREACH != (e)) {                  \
0282                 ch->ninfo = 1;                                                                 \
0283                 ch->nallocated = 3;                                                            \
0284                 PMIX_INFO_CREATE(ch->info, ch->nallocated);                                    \
0285                 /* mark for non-default handlers only */                                       \
0286                 PMIX_INFO_LOAD(&ch->info[0], PMIX_EVENT_NON_DEFAULT, NULL, PMIX_BOOL);         \
0287             } else {                                                                           \
0288                 ch->nallocated = 2;                                                            \
0289                 PMIX_INFO_CREATE(ch->info, ch->nallocated);                                    \
0290             }                                                                                  \
0291             ch->final_cbfunc = (f);                                                            \
0292             ch->final_cbdata = ch;                                                             \
0293             /* cache it */                                                                     \
0294             pmix_list_append(&pmix_globals.cached_events, &ch->super);                         \
0295             ch->timer_active = true;                                                           \
0296             pmix_event_assign(&ch->ev, pmix_globals.evbase, -1, 0, pmix_event_timeout_cb, ch); \
0297             PMIX_POST_OBJECT(ch);                                                              \
0298             pmix_event_add(&ch->ev, &pmix_globals.event_window);                               \
0299         } else {                                                                               \
0300             /* add this peer to the array of sources */                                        \
0301             pmix_proc_t proc_tmp;                                                              \
0302             pmix_info_t *info_tmp;                                                             \
0303             size_t ninfo_tmp;                                                                  \
0304             pmix_strncpy(proc_tmp.nspace, (p)->nptr->nspace, PMIX_MAX_NSLEN);                  \
0305             proc_tmp.rank = (p)->info->pname.rank;                                             \
0306             ninfo_tmp = ch->nallocated + 1;                                                    \
0307             PMIX_INFO_CREATE(info_tmp, ninfo_tmp);                                             \
0308             /* must keep the hdlr name and return object at the end, so prepend */             \
0309             PMIX_INFO_LOAD(&info_tmp[0], PMIX_PROCID, &proc_tmp, PMIX_PROC);                   \
0310             for (_n = 0; _n < ch->ninfo; _n++) {                                               \
0311                 PMIX_INFO_XFER(&info_tmp[_n + 1], &ch->info[_n]);                              \
0312             }                                                                                  \
0313             PMIX_INFO_FREE(ch->info, ch->nallocated);                                          \
0314             ch->nallocated = ninfo_tmp;                                                        \
0315             ch->info = info_tmp;                                                               \
0316             ch->ninfo = ninfo_tmp - 2;                                                         \
0317             /* reset the timer */                                                              \
0318             if (ch->timer_active) {                                                            \
0319                 pmix_event_del(&ch->ev);                                                       \
0320             }                                                                                  \
0321             PMIX_POST_OBJECT(ch);                                                              \
0322             ch->timer_active = true;                                                           \
0323             pmix_event_add(&ch->ev, &pmix_globals.event_window);                               \
0324         }                                                                                      \
0325     } while (0)
0326 
0327 END_C_DECLS
0328 
0329 #endif /* PMIX_EVENT_H */