NewMadeleine

Documentation

nm_core_interface.h
Go to the documentation of this file.
1/*
2 * NewMadeleine
3 * Copyright (C) 2006-2024 (see AUTHORS file)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at
8 * your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 */
15
16
17#ifndef NM_CORE_INTERFACE_H
18#define NM_CORE_INTERFACE_H
19
22#include <nm_public.h>
23#include <nm_log.h>
24#include <Padico/Puk.h>
25#include <sys/uio.h>
26
27#ifdef PIOMAN
28#include <pioman.h>
29#else
30#include <pthread.h>
31#endif
32
46/* ** Core init ******************************************** */
47
48typedef struct nm_core*nm_core_t;
49
50puk_component_t nm_core_component_load(const char*entity, const char*name);
51
52int nm_core_init(nm_core_t *pp_core);
53
54int nm_core_set_strategy(nm_core_t p_core, puk_component_t strategy);
55
57
60
62extern struct nm_core_internal_s
63{
66
68static inline nm_core_t nm_core_get_singleton(void)
69{
71}
72
73
74/* ** Drivers ********************************************** */
75
77typedef struct nm_drv_s*nm_drv_t;
78
80
82 nm_drv_t *pp_drv, const char**p_url);
83
84
85/* ** Gates ************************************************ */
86
93
94
95/* ** Threads ********************************************** */
96
98 {
103 };
105
109
114
115/* ** Progression ****************************************** */
116
118
119/* ** Status *********************************************** */
120
121#ifdef PIOMAN
123typedef piom_cond_value_t nm_status_t;
125typedef piom_cond_t nm_cond_status_t;
126#else /* PIOMAN */
128typedef uint32_t nm_status_t;
131#endif /* PIOMAN */
132
133/* ** status and flags, used in pack/unpack requests and events */
134
136#define NM_STATUS_NONE ((nm_status_t)0x00000000)
138#define NM_STATUS_PACK_INIT ((nm_status_t)0x00000001)
140#define NM_STATUS_UNPACK_INIT ((nm_status_t)0x00000002)
142#define NM_STATUS_PACK_COMPLETED ((nm_status_t)0x00000004)
144#define NM_STATUS_UNPACK_COMPLETED ((nm_status_t)0x00000008)
146#define NM_STATUS_UNEXPECTED ((nm_status_t)0x00000010)
148#define NM_STATUS_UNPACK_CANCELLED ((nm_status_t)0x00000020)
150#define NM_STATUS_PACK_POSTED ((nm_status_t)0x00000040)
152#define NM_STATUS_UNPACK_POSTED ((nm_status_t)0x00000080)
154#define NM_STATUS_ACK_RECEIVED ((nm_status_t)0x00000100)
156#define NM_STATUS_UNPACK_DATA0 ((nm_status_t)0x00000200)
158#define NM_STATUS_UNPACK_DATA_SIZE ((nm_status_t)0x00000400)
160#define NM_STATUS_FINALIZED ((nm_status_t)0x00000800)
162#define NM_STATUS_ERROR ((nm_status_t)0x00001000)
164#define NM_STATUS_PACK_MSG_SIZE ((nm_status_t)0x00002000)
166#define NM_STATUS_UNPACK_PREFETCHED ((nm_status_t)0x00004000)
167
169#define NM_STATUS_MASK_FULL ((nm_status_t)-1)
170
171
173typedef uint32_t nm_req_flag_t;
174
176#define NM_REQ_FLAG_NONE ((nm_req_flag_t)0x00000000)
178#define NM_REQ_FLAG_PACK_SYNCHRONOUS ((nm_req_flag_t)0x00001000)
180#define NM_REQ_FLAG_PACK ((nm_req_flag_t)0x00002000)
182#define NM_REQ_FLAG_UNPACK ((nm_req_flag_t)0x00004000)
184#define NM_REQ_FLAG_UNPACK_DATA_INFO ((nm_req_flag_t)0x00008000)
186#define NM_REQ_FLAG_UNPACK_MATCHING_INFO ((nm_req_flag_t)0x00010000)
188#define NM_REQ_FLAG_UNPACK_PREFETCHING ((nm_req_flag_t)0x00020000)
190#define NM_REQ_FLAG_MATCHING_WILDCARD ((nm_req_flag_t)0x00100000)
192#define NM_REQ_FLAG_MATCHING_GATE ((nm_req_flag_t)0x00200000)
194#define NM_REQ_FLAG_MATCHING_TAG ((nm_req_flag_t)0x00400000)
196#define NM_REQ_FLAG_MATCHING_FULL ((nm_req_flag_t)0x00800000)
198#define NM_REQ_FLAG_FINALIZE_LATER ((nm_req_flag_t)0x01000000)
200#define NM_REQ_FLAG_UNPACK_PARTITIONED ((nm_req_flag_t)0x02000000)
202#define NM_REQ_FLAG_PACK_PARTITIONED ((nm_req_flag_t)0x04000000)
203
205typedef uint32_t nm_req_chunk_flag_t;
206
208#define NM_REQ_CHUNK_FLAG_NONE ((nm_req_chunk_flag_t)0x00000000)
210#define NM_REQ_CHUNK_FLAG_SHORT ((nm_req_chunk_flag_t)0x00020000)
212#define NM_REQ_CHUNK_FLAG_USE_COPY ((nm_req_chunk_flag_t)0x00080000)
214#define NM_REQ_CHUNK_FLAG_DATA_ITERATOR ((nm_req_chunk_flag_t)0x00100000)
215
216
217/* ** tags ************************************************* */
218
220typedef uint32_t nm_session_hash_t;
221
223#define NM_CORE_TAG_HASH_FULL ((nm_session_hash_t)0xFFFFFFFF)
224
227{
230} __attribute__((packed));
231
233
234#define NM_CORE_TAG_MASK_FULL ((nm_core_tag_t){ .tag = NM_TAG_MASK_FULL, .hashcode = NM_CORE_TAG_HASH_FULL })
235#define NM_CORE_TAG_NONE ((nm_core_tag_t){ .tag = 0, .hashcode = 0x0 })
236
238{
239 nm_core_tag_t core_tag;
240 core_tag.tag = tag;
241 core_tag.hashcode = hashcode;
242 return core_tag;
243}
245{
246 return core_tag.tag;
247}
249{
250 return core_tag.hashcode;
251}
252
253
254/* ** Event notification *********************************** */
255
258{
266
268typedef void (*nm_core_event_notifier_t)(const struct nm_core_event_s*const event, void*ref);
269
272{
276};
277
280{
283 void*ref;
284};
285
288{
291};
297void nm_core_req_monitor(struct nm_core*p_core, struct nm_req_s*p_req, struct nm_monitor_s monitor);
298
299
301#define NM_EVENT_MATCHING_ANY ((struct nm_core_event_matching_s){ .p_gate = NM_ANY_GATE, .tag = NM_CORE_TAG_NONE, .tag_mask = NM_CORE_TAG_NONE })
302
303#define NM_MONITOR_NULL ((struct nm_monitor_s){ .p_notifier = NULL, .event_mask = 0, .ref = NULL })
304
305#define NM_CORE_MONITOR_NULL ((struct nm_core_monitor_s){ .monitor = NM_MONITOR_NULL, .matching = NM_EVENT_MATCHING_ANY })
306
307
308/* ** Packs/unpacks **************************************** */
309
311{
314};
315
318{
323};
324#define NM_MATCHING_CONTAINER_NULL ((struct nm_matching_container_s) { NULL })
325
326
328 {
336 };
338
351{
353 union
354 {
355 struct
356 {
359 struct
360 {
363 struct
364 {
365 struct nm_pkt_wrap_s*p_pw;
367 struct
368 {
371 struct
372 {
373 struct nm_pkt_wrap_s*p_pw;
375 struct
376 {
377 void (*p_handler)(void);
380};
381
383
386{
387 PUK_LIST_LINK(nm_req_chunk);
394};
395
397
400{
410 int err;
411 union
412 {
413 struct
414 {
419 uint32_t checksum;
421 struct
422 {
429 struct
430 {
432 struct nm_req_pchunk_s
433 {
434 struct nm_req_pchunk_s*p_next;
441 };
443};
444
446void nm_core_pack_init(struct nm_core*p_core, struct nm_req_s*p_pack);
447
449void nm_core_pack_data(nm_core_t p_core, struct nm_req_s*p_pack, const struct nm_data_s*p_data);
450
453
455void nm_core_pack_submit(struct nm_core*p_core, struct nm_req_s*p_pack);
456
458void nm_core_pack_set_priority(struct nm_core*p_core, struct nm_req_s*p_pack, nm_prio_t priority);
459
461static inline void nm_core_pack_set_hlen(struct nm_core*p_core __attribute__((unused)), struct nm_req_s*p_pack, nm_len_t hlen)
462{
463 p_pack->pack.hlen = hlen;
464}
465
466void nm_core_pack_submit_chunks(struct nm_core*p_core, struct nm_req_s*p_pack, int n, const struct nm_chunk_s*p_chunks);
467
469void nm_core_unpack_init(struct nm_core*p_core, struct nm_req_s*p_unpack);
470
472void nm_core_unpack_offset(struct nm_core*p_core, struct nm_req_s*p_unpack, nm_len_t offset);
473
475void nm_core_unpack_data(struct nm_core*p_core, struct nm_req_s*p_unpack, const struct nm_data_s*p_data);
476
479
481void nm_core_unpack_match_event(struct nm_core*p_core, struct nm_req_s*p_unpack, const struct nm_core_event_s*p_event);
482
484void nm_core_unpack_submit(struct nm_core*p_core, struct nm_req_s*p_unpack, nm_req_flag_t flags);
485
487int nm_core_unpack_peek(struct nm_core*p_core, struct nm_req_s*p_unpack, const struct nm_data_s*p_data,
488 nm_len_t peek_offset, nm_len_t peek_len);
489
492int nm_core_unpack_iprobe(struct nm_core*p_core, struct nm_req_s*p_unpack);
493
497int nm_core_unpack_cancel(struct nm_core*p_core, struct nm_req_s*p_unpack);
498
500int nm_core_iprobe(struct nm_core*p_core,
502 nm_gate_t *pp_out_gate, nm_core_tag_t*p_out_tag, nm_len_t*p_out_size);
503
505void nm_core_flush(struct nm_core*p_core);
506
507
508/* ** Packet injection from outside of nmad core */
509
512
519typedef void(*nm_injector_pull_data_t)(struct nm_req_s*p_req, const struct nm_data_s*p_data, nm_len_t chunk_offset, nm_len_t chunk_len, void*p_ref);
520
524 nm_len_t chunk_offset, nm_len_t chunk_len, int is_last_chunk,
525 nm_injector_pull_data_t p_pull_data, void*p_ref);
526
529
531void nm_core_inject_finalize(struct nm_core*p_core, struct nm_req_s*p_req);
532
535
536/* ** partitioned unpack */
537
538void nm_core_unpack_partition_set(struct nm_req_s*p_unpack, int n_partitions);
539
541
542int nm_core_unpack_partition_test(struct nm_req_s*p_unpack, int partition);
543
544/* ** Core tasks */
545
547void nm_core_task_submit_locked(struct nm_core*p_core, void (*p_handler)(void));
548
550void nm_core_task_submit_unlocked(struct nm_core*p_core, void (*p_handler)(void));
551
552
553/* ** synchronization primitives *************************** */
554
567static inline void nm_cond_init(nm_cond_status_t*p_cond, nm_status_t bitmask);
568
570static inline void nm_cond_destroy(nm_cond_status_t*p_cond);
571
573static inline nm_status_t nm_cond_test(const nm_cond_status_t*p_cond, nm_status_t bitmask);
574
576static inline nm_status_t nm_cond_test_locked(const nm_cond_status_t*p_cond, nm_status_t bitmask);
577
580static inline void nm_cond_add(nm_cond_status_t*p_cond, nm_status_t bitmask);
581
583static inline void nm_cond_wait(nm_cond_status_t*p_cond, nm_status_t bitmask, nm_core_t p_core);
584
586static inline void nm_cond_signal(nm_cond_status_t*p_cond, nm_status_t bitmask);
587
589static inline void nm_cond_wait_all(void**pp_conds, int n, uintptr_t offset, nm_status_t bitmask, nm_core_t p_core);
590
593#if defined(PIOMAN)
594
596static inline void nm_cond_init(nm_cond_status_t*p_cond, nm_status_t bitmask)
597{
598 piom_cond_init(p_cond, bitmask);
599}
601static inline void nm_cond_destroy(nm_cond_status_t*p_cond)
602{
603 piom_cond_destroy(p_cond);
604}
606static inline nm_status_t nm_cond_test(const nm_cond_status_t*p_cond, nm_status_t bitmask)
607{
608 return piom_cond_test(p_cond, bitmask);
609}
611static inline nm_status_t nm_cond_test_locked(const nm_cond_status_t*p_cond, nm_status_t bitmask)
612{
613 return piom_cond_test_locked((nm_cond_status_t*)p_cond, bitmask);
614}
616static inline void nm_cond_add(nm_cond_status_t*p_cond, nm_status_t bitmask)
617{
618 piom_cond_add(p_cond, bitmask);
619}
621static inline void nm_cond_mask(nm_cond_status_t*p_cond, nm_status_t bitmask)
622{
623 piom_cond_mask(p_cond, bitmask);
624}
626static inline void nm_cond_wait(nm_cond_status_t*p_cond, nm_status_t bitmask, nm_core_t p_core __attribute__((unused)))
627{
628 piom_cond_wait(p_cond, bitmask);
629}
631static inline void nm_cond_signal(nm_cond_status_t*p_cond, nm_status_t bitmask)
632{
633 piom_cond_signal(p_cond, bitmask);
634}
636static inline void nm_cond_wait_all(void**pp_conds, int n, uintptr_t offset, nm_status_t bitmask, nm_core_t p_core __attribute__((unused)))
637{
638 piom_cond_wait_all(pp_conds, n, offset, bitmask);
639}
640#else /* PIOMAN */
642static inline void nm_cond_init(nm_cond_status_t*p_cond, nm_status_t bitmask)
643{
644 *p_cond = bitmask;
645}
647static inline void nm_cond_destroy(nm_cond_status_t*p_cond __attribute__((unused)))
648{
649}
651static inline nm_status_t nm_cond_test(const nm_cond_status_t*p_cond, nm_status_t bitmask)
652{
653 return ((*p_cond) & bitmask);
654}
657{
658 return nm_cond_test(p_cond, bitmask);
659}
661static inline void nm_cond_add(nm_cond_status_t*p_cond, nm_status_t bitmask)
662{
663 *p_cond |= bitmask;
664}
666static inline void nm_cond_mask(nm_cond_status_t*p_cond, nm_status_t bitmask)
667{
668 *p_cond &= ~bitmask;
669}
671static inline void nm_cond_signal(nm_cond_status_t*p_cond, nm_status_t bitmask)
672{
673 *p_cond |= bitmask;
674}
676static inline void nm_cond_wait(nm_cond_status_t*p_cond, nm_status_t bitmask, nm_core_t p_core)
677{
678 while(!nm_cond_test(p_cond, bitmask))
679 {
680 nm_schedule(p_core);
681 }
682}
684static inline void nm_cond_wait_all(void**pp_conds, int n, uintptr_t offset, nm_status_t bitmask, nm_core_t p_core)
685{
686 int i;
687 for(i = 0; i < n; i++)
688 {
689 if(pp_conds[i] != NULL)
690 {
691 nm_cond_status_t*p_cond = (nm_cond_status_t*)((uintptr_t)pp_conds[i] + offset);
692 nm_cond_wait(p_cond, bitmask, p_core);
693 }
694 }
695}
696#endif /* PIOMAN */
697
698/* ** convenient frontends to deal with status in requests */
699
701static inline void nm_status_init(struct nm_req_s*p_req, nm_status_t bitmask)
702{
703 nm_cond_init(&p_req->status, bitmask);
704}
705static inline void nm_status_destroy(struct nm_req_s*p_req)
706{
707 nm_cond_destroy(&p_req->status);
708}
710static inline nm_status_t nm_status_test(const struct nm_req_s*p_req, nm_status_t bitmask)
711{
712 if(bitmask & NM_STATUS_FINALIZED) /* status FINALIZED needs strong consistency to avoid use after free */
713 return nm_cond_test_locked(&p_req->status, bitmask);
714 else
715 return nm_cond_test(&p_req->status, bitmask);
716}
717static inline void nm_status_add(struct nm_req_s*p_req, nm_status_t bitmask)
718{
719 nm_cond_add(&p_req->status, bitmask);
720}
722static inline void nm_status_unset(struct nm_req_s*p_req, nm_status_t bitmask)
723{
724 nm_cond_mask(&p_req->status, bitmask);
725}
727static inline void nm_status_wait(struct nm_req_s*p_req, nm_status_t bitmask, nm_core_t p_core)
728{
729 nm_cond_wait(&p_req->status, bitmask, p_core);
730 assert(nm_status_test(p_req, bitmask) != 0);
731}
732static inline void nm_status_signal(struct nm_req_s*p_req, nm_status_t bitmask)
733{
734 nm_cond_signal(&p_req->status, bitmask);
735}
737static inline void nm_status_wait_all(void**pp_reqs, int n, uintptr_t offset,
738 nm_status_t bitmask, nm_core_t p_core)
739{
740 const struct nm_req_s*p_req = NULL;
741 const uintptr_t status_offset = (uintptr_t)&p_req->status - (uintptr_t)p_req; /* offset of 'status' in nm_req_s */
742 nm_cond_wait_all(pp_reqs, n, offset + status_offset, bitmask, p_core);
743}
744static inline void nm_status_assert(struct nm_req_s*p_req __attribute__((unused)), nm_status_t value __attribute__((unused)))
745{
746 assert(nm_status_test(p_req, NM_STATUS_MASK_FULL) == value);
747}
748
749static inline void nm_status_spinwait(struct nm_req_s*p_req, nm_status_t status)
750{
751 while(!nm_status_test(p_req, status))
752 { /* bust wait*/ }
753}
755static inline int nm_status_test_allbits(struct nm_req_s*p_req, nm_status_t bitmask)
756{
757 return (nm_status_test(p_req, bitmask) == bitmask);
758}
759
760/* ** frontends for atomic ops ***************************** */
761
763static inline void nm_mem_fence_always(void)
764{
765 __sync_synchronize();
766}
767
769static inline void nm_mem_fence(void)
770{
771#if defined(PIOMAN_MULTITHREAD)
772 __sync_synchronize();
773#else
774 nm_core_t p_core = nm_core_get_singleton();
776 {
777 __sync_synchronize();
778 }
779#endif /* PIOMAN_MULTITHREAD */
780}
781
783static inline int nm_atomic_inc(int*v)
784{
785#if defined(PIOMAN_MULTITHREAD)
786 return __sync_fetch_and_add(v, 1);
787#else
788 nm_core_t p_core = nm_core_get_singleton();
790 {
791 return __sync_fetch_and_add(v, 1);
792 }
793 else
794 {
795 return (*v)++;
796 }
797#endif /* PIOMAN_MULTITHREAD */
798}
799
801static inline int nm_atomic_alway_inc(int*v)
802{
803 return __sync_fetch_and_add(v, 1);
804}
805
807static inline int nm_atomic_dec(int*v)
808{
809#if defined(PIOMAN_MULTITHREAD)
810 return __sync_sub_and_fetch(v, 1);
811#else
812 nm_core_t p_core = nm_core_get_singleton();
814 {
815 return __sync_sub_and_fetch(v, 1);
816 }
817 else
818 {
819 return --(*v);
820 }
821#endif /* PIOMAN_MULTITHREAD */
822}
823
825static inline int nm_atomic_always_dec(int*v)
826{
827 return __sync_sub_and_fetch(v, 1);
828}
829
831static inline void nm_atomic_add(int*v, int v2)
832{
833#if defined(PIOMAN_MULTITHREAD)
834 __sync_fetch_and_add(v, v2);
835#else
836 nm_core_t p_core = nm_core_get_singleton();
838 {
839 __sync_fetch_and_add(v, v2);
840 }
841 else
842 {
843 (*v) += v2;
844 }
845#endif /* PIOMAN_MULTITHREAD */
846}
847
849static inline void nm_atomic_always_add(int*v, int v2)
850{
851 __sync_fetch_and_add(v, v2);
852}
853
855static inline int nm_atomic_compare_and_swap(int*v, int oldval, int newval)
856{
857#if defined(PIOMAN_MULTITHREAD)
858 return __sync_bool_compare_and_swap(v, oldval, newval);
859#else
860 nm_core_t p_core = nm_core_get_singleton();
862 {
863 return __sync_bool_compare_and_swap(v, oldval, newval);
864 }
865 else
866 {
867 if(*v == oldval)
868 {
869 *v = newval;
870 return 1;
871 }
872 else
873 {
874 return 0;
875 }
876 }
877#endif /* PIOMAN_MULTITHREAD */
878}
879
881static inline int nm_atomic_always_compare_and_swap(int*v, int oldval, int newval)
882{
883 return __sync_bool_compare_and_swap(v, oldval, newval);
884}
885
886/* ** frontend for generic locking ************************* */
887
888/*
889 * locking with pioman:
890 * always use all locks (even if the application is not threaded, pioman itself is threaded).
891 *
892 * locking without pioman:
893 * - single : no locking
894 * - funneled : lock in rcache
895 * - serialized : + mem fence in spinlocks (no locks) + lock in allocators + atomics in refcounts
896 * - multiple : not supported without pioman
897 */
898
899#ifdef PIOMAN
900typedef piom_spinlock_t nm_spinlock_t;
901#else /* PIOMAN */
903{
904#ifdef NMAD_DEBUG
905 int lock;
906 pthread_t last_tid;
907#endif /* NMAD_DEBUG */
908};
910#endif /* PIOMAN */
911
913static inline void nm_spin_init(nm_spinlock_t*p_spin);
914
916static inline void nm_spin_destroy(nm_spinlock_t*p_spin);
917
919static inline void nm_spin_lock(nm_spinlock_t*p_spin);
920
922static inline void nm_spin_unlock(nm_spinlock_t*p_spin);
923
927static inline int nm_spin_trylock(nm_spinlock_t*p_spin);
928
930static inline void nm_spin_assert_locked(nm_spinlock_t*p_spin);
931
933static inline void nm_spin_assert_notlocked(nm_spinlock_t*p_spin);
934
935
937static inline void nm_spin_check_nothread(nm_spinlock_t*p_spin __attribute__((unused)))
938{
939#if defined(NMAD_DEBUG) && !defined(PIOMAN)
940 nm_core_t p_core = nm_core_get_singleton();
942 if(p_spin->last_tid == (pthread_t)0)
943 {
944 p_spin->last_tid = pthread_self();
945 __sync_synchronize();
946 }
947 else
948 {
949 if(p_spin->last_tid != pthread_self())
950 {
951 NM_FATAL("detected calls from multiple threads in non-threaded mode. Please use pioman-enabled build for multi-threaded use or give thread level using nm_core_set_thread_level(NM_THREAD_SERIALIZED) for serialized thread level.");
952 }
953 }
954#endif /* NMAD_DEBUG && !PIOMAN */
955}
956
958static inline void nm_spin_clear_nothread(nm_spinlock_t*p_spin __attribute__((unused)))
959{
960#if defined(NMAD_DEBUG) && !defined(PIOMAN)
961 nm_core_t p_core = nm_core_get_singleton();
963 if(p_spin->last_tid == 0)
964 {
965 NM_FATAL("unlocking while no thread is holding the lock.");
966 }
967 else if(p_spin->last_tid != pthread_self())
968 {
969 NM_WARN("unlocking from another thread than where lock was acquired.\n");
970 }
972 {
973 p_spin->last_tid = (pthread_t)0;
974 }
975#endif /* NMAD_DEBUG && !PIOMAN */
976}
977
978static inline void nm_spin_init(nm_spinlock_t*p_spin __attribute__((unused)))
979{
980#ifdef PIOMAN
981 piom_spin_init(p_spin);
982#else /* PIOMAN */
983#ifdef NMAD_DEBUG
984 p_spin->lock = 0;
985 p_spin->last_tid = 0;
986#endif /* NMAD_DEBUG */
987#endif /* PIOMAN */
988}
989
990static inline void nm_spin_destroy(nm_spinlock_t*p_spin __attribute__((unused)))
991{
992#ifdef PIOMAN
993 piom_spin_destroy(p_spin);
994#else /* PIOMAN */
995#ifdef NMAD_DEBUG
996 assert(p_spin->lock == 0);
997#endif /* NMAD_DEBUG */
998#endif /* PIOMAN */
999}
1000
1001static inline void nm_spin_lock(nm_spinlock_t*p_spin __attribute__((unused)))
1002{
1003#ifdef PIOMAN
1004 piom_spin_lock(p_spin);
1005#else /* PIOMAN */
1006#ifdef NMAD_DEBUG
1007 __sync_synchronize();
1008 if(p_spin->lock != 0)
1009 {
1010 NM_FATAL("spinlock is not free in nm_spin_lock(); detected concurrent access from thread = %p. Suspecting multi-threaded use by the application while library is initialized in non-threaded mode.\n",
1011 (void*)p_spin->last_tid);
1012 }
1013 p_spin->lock = 1;
1014#endif /* NMAD_DEBUG */
1015 nm_spin_check_nothread(p_spin);
1016 nm_core_t p_core = nm_core_get_singleton();
1018 {
1019 __sync_synchronize();
1020 }
1021#endif /* PIOMAN */
1022}
1023
1024static inline void nm_spin_unlock(nm_spinlock_t*p_spin __attribute__((unused)))
1025{
1026#ifdef PIOMAN
1027 piom_spin_unlock(p_spin);
1028#else /* PIOMAN */
1029 nm_spin_clear_nothread(p_spin);
1030#ifdef NMAD_DEBUG
1031 __sync_synchronize();
1032 assert(p_spin->lock == 1);
1033 p_spin->lock = 0;
1034#endif /* NMAD_DEBUG */
1035 nm_core_t p_core = nm_core_get_singleton();
1037 {
1038 __sync_synchronize();
1039 }
1040#endif /* PIOMAN */
1041}
1042
1043static inline int nm_spin_trylock(nm_spinlock_t*p_spin __attribute__((unused)))
1044{
1045#ifdef PIOMAN
1046 return piom_spin_trylock(p_spin);
1047#else /* PIOMAN */
1048 int rc = 1;
1049#ifdef NMAD_DEBUG
1050 __sync_synchronize();
1051 if(p_spin->lock)
1052 {
1053 assert(p_spin->lock == 1);
1054 rc = 0;
1055 }
1056 else
1057 {
1058 rc = 1;
1059 p_spin->lock = 1;
1060 nm_spin_check_nothread(p_spin);
1061 }
1062#endif /* NMAD_DEBUG */
1063 nm_core_t p_core = nm_core_get_singleton();
1065 {
1066 __sync_synchronize();
1067 }
1068 return rc;
1069#endif /* PIOMAN */
1070}
1071
1072static inline void nm_spin_assert_locked(nm_spinlock_t*p_spin __attribute__((unused)))
1073{
1074#ifdef PIOMAN
1075 piom_spin_assert_locked(p_spin);
1076#else /* PIOMAN */
1077#ifdef NMAD_DEBUG
1078 assert(p_spin->lock == 1);
1079 assert(p_spin->last_tid == pthread_self());
1080#endif /* NMAD_DEBUG */
1081#endif /* PIOMAN */
1082}
1083
1084static inline void nm_spin_assert_notlocked(nm_spinlock_t*p_spin __attribute__((unused)))
1085{
1086#ifdef PIOMAN
1087 piom_spin_assert_notlocked(p_spin);
1088#else /* PIOMAN */
1089#ifdef NMAD_DEBUG
1090 assert(p_spin->lock == 0);
1091#endif /* NMAD_DEBUG */
1092#endif /* PIOMAN */
1093}
1094
1095
1098#endif /* NM_CORE_INTERFACE_H */
int nm_core_driver_load_init(nm_core_t p_core, puk_component_t driver, nm_trk_kind_t kind, nm_drv_t *pp_drv, const char **p_url)
int nm_core_unpack_iprobe(struct nm_core *p_core, struct nm_req_s *p_unpack)
probes whether an incoming packet matched this unposted request.
void nm_core_inject_finalize(struct nm_core *p_core, struct nm_req_s *p_req)
finalize an injected request that was only completed.
int nm_core_unpack_cancel(struct nm_core *p_core, struct nm_req_s *p_unpack)
cancel a pending unpack
void nm_core_pack_data(nm_core_t p_core, struct nm_req_s *p_pack, const struct nm_data_s *p_data)
build a pack request from data descriptor
PUK_LIST_DECLARE_TYPE(nm_req_chunk)
void nm_core_unpack_init(struct nm_core *p_core, struct nm_req_s *p_unpack)
initializes an empty unpack request
static int nm_atomic_compare_and_swap(int *v, int oldval, int newval)
boolean int compare and swap, atomic only when multithread
puk_component_t nm_core_component_load(const char *entity, const char *name)
int nm_core_unpack_peek(struct nm_core *p_core, struct nm_req_s *p_unpack, const struct nm_data_s *p_data, nm_len_t peek_offset, nm_len_t peek_len)
peeks unexpected data without consumming it.
void nm_core_monitor_add(nm_core_t p_core, struct nm_core_monitor_s *m)
Register an event monitor.
void nm_core_schedopt_disable(nm_core_t p_core)
disable schedopt for raw driver use
int nm_core_unpack_partition_test(struct nm_req_s *p_unpack, int partition)
void nm_core_inject_chunk(struct nm_core *p_core, nm_gate_t p_gate, nm_core_tag_t tag, nm_seq_t seq, nm_len_t chunk_offset, nm_len_t chunk_len, int is_last_chunk, nm_injector_pull_data_t p_pull_data, void *p_ref)
inject a packet in nmad core as if it arrived from network.
int nm_core_iprobe(struct nm_core *p_core, nm_gate_t p_gate, nm_core_tag_t tag, nm_core_tag_t tag_mask, nm_gate_t *pp_out_gate, nm_core_tag_t *p_out_tag, nm_len_t *p_out_size)
probe unexpected packet, check matching for (packet_tag & tag_mask) == tag
void nm_core_pack_send(struct nm_core *p_core, struct nm_req_s *p_pack, nm_core_tag_t tag, nm_gate_t p_gate, nm_req_flag_t flags)
set tag/gate/flags for pack request
nm_status_t nm_cond_status_t
status with synchronization (wait/signal)
static void nm_atomic_always_add(int *v, int v2)
int add, always atomic
void(* nm_injector_pull_data_t)(struct nm_req_s *p_req, const struct nm_data_s *p_data, nm_len_t chunk_offset, nm_len_t chunk_len, void *p_ref)
user-supplied function called to pull data to posted request through nmad core p_req is the user requ...
struct nm_core * nm_core_t
nm_core_task_kind_e
int nm_schedule(nm_core_t p_core)
static void nm_status_signal(struct nm_req_s *p_req, nm_status_t bitmask)
void nm_core_unpack_offset(struct nm_core *p_core, struct nm_req_s *p_unpack, nm_len_t offset)
set an offset on data; data before offset will be discarded
uint32_t nm_req_flag_t
pack/unpack flags
#define NM_STATUS_FINALIZED
request is finalized, may be freed
static void nm_spin_check_nothread(nm_spinlock_t *p_spin __attribute__((unused)))
check that we are always called from the same thread in case of non-threaded mode
void nm_core_unpack_match_recv(struct nm_core *p_core, struct nm_req_s *p_unpack, nm_gate_t p_gate, nm_core_tag_t tag, nm_core_tag_t tag_mask)
match an unpack request with given gate/tag, next sequence number assumed
static int nm_atomic_dec(int *v)
decrement int, atomic only when multithread
static void nm_spin_init(nm_spinlock_t *p_spin)
init the spin lock
void(* nm_core_event_notifier_t)(const struct nm_core_event_s *const event, void *ref)
an event notifier, fired upon status transition
void nm_core_pack_init(struct nm_core *p_core, struct nm_req_s *p_pack)
initializes an empty pack request
void nm_core_inject_complete_finalize(struct nm_core *p_core, struct nm_req_s *p_req, nm_len_t chunk_offset, nm_len_t chunk_len)
notify data was injected in a matched request and finalize this request.
static nm_session_hash_t nm_core_tag_get_hashcode(nm_core_tag_t core_tag)
#define NM_STATUS_MASK_FULL
mask to catch all bits of status
static void nm_spin_assert_notlocked(nm_spinlock_t *p_spin)
assert that current thread doesn't hold the lock
void nm_core_unpack_partition_set(struct nm_req_s *p_unpack, int n_partitions)
struct nm_core_event_s __attribute__
void nm_core_pack_submit(struct nm_core *p_core, struct nm_req_s *p_pack)
post a pack request
nm_thread_level_e
void nm_core_inject_complete(struct nm_core *p_core, struct nm_req_s *p_req, nm_len_t chunk_offset, nm_len_t chunk_len)
notify data was injected in a matched request, but do not finalize the request (the status will be NM...
struct nm_drv_s * nm_drv_t
a nmad driver; opaque type for the user
struct nm_core_internal_s nm_core_internal
static void nm_status_wait_all(void **pp_reqs, int n, uintptr_t offset, nm_status_t bitmask, nm_core_t p_core)
wait for all reqs, any bit in bitmask
int nm_core_exit(nm_core_t p_core)
uint32_t nm_session_hash_t
a session hashcode in tags, used to multiplex sessions
void nm_core_unpack_data(struct nm_core *p_core, struct nm_req_s *p_unpack, const struct nm_data_s *p_data)
build an unpack request from data descriptor
enum nm_core_task_kind_e nm_core_task_kind_t
static void nm_status_unset(struct nm_req_s *p_req, nm_status_t bitmask)
remove bits of bitmask from req status
nm_thread_level_t nm_core_get_thread_level(nm_core_t)
Get the current thread level.
static int nm_spin_trylock(nm_spinlock_t *p_spin)
try to lock the spin lock return 1 if lock is successfully acquired, 0 otherwise
static void nm_spin_clear_nothread(nm_spinlock_t *p_spin __attribute__((unused)))
clear the last_tid tracking for lock consistency checking
void nm_core_flush(struct nm_core *p_core)
Flush pending packs (if supported by the strategy).
static int nm_atomic_always_dec(int *v)
decrement int, always atomic
enum nm_thread_level_e nm_thread_level_t
static void nm_core_pack_set_hlen(struct nm_core *p_core __attribute__((unused)), struct nm_req_s *p_pack, nm_len_t hlen)
set a header length for the given pack request
uint32_t nm_status_t
status bits of pack/unpack requests
static nm_core_tag_t nm_core_tag_build(nm_session_hash_t hashcode, nm_tag_t tag)
static void nm_status_spinwait(struct nm_req_s *p_req, nm_status_t status)
int nm_core_set_strategy(nm_core_t p_core, puk_component_t strategy)
static void nm_status_init(struct nm_req_s *p_req, nm_status_t bitmask)
initialize cond status with given initial value
static void nm_spin_destroy(nm_spinlock_t *p_spin)
destroy the spin lock
PUK_VECT_TYPE(nm_drv, nm_drv_t)
static int nm_atomic_inc(int *v)
increment int, atomic only when multithread
nm_gate_t nm_core_gate_new(nm_core_t p_core, nm_drv_vect_t *p_drvs)
Init a new gate, using the given set of drivers.
static int nm_status_test_allbits(struct nm_req_s *p_req, nm_status_t bitmask)
tests for all given bits in status
void nm_core_unpack_match_event(struct nm_core *p_core, struct nm_req_s *p_unpack, const struct nm_core_event_s *p_event)
match an unpack request with a packet that triggered an event
static nm_tag_t nm_core_tag_get_tag(nm_core_tag_t core_tag)
static void nm_status_destroy(struct nm_req_s *p_req)
struct nm_spinlock_s nm_spinlock_t
static void nm_spin_lock(nm_spinlock_t *p_spin)
acquire the spin lock
void nm_core_unpack_partition_free(struct nm_req_s *p_unpack)
static void nm_cond_mask(nm_cond_status_t *p_cond, nm_status_t bitmask)
void nm_core_task_submit_unlocked(struct nm_core *p_core, void(*p_handler)(void))
submit task lock-free to the submission list
static void nm_mem_fence_always(void)
memory fence, always
void nm_core_unpack_submit(struct nm_core *p_core, struct nm_req_s *p_unpack, nm_req_flag_t flags)
submit an unpack request
static void nm_spin_assert_locked(nm_spinlock_t *p_spin)
assert that current thread holds the lock
static int nm_atomic_always_compare_and_swap(int *v, int oldval, int newval)
boolean int compare and swap, always atomic
void nm_core_set_thread_level(nm_thread_level_t)
Sets the thread level before nm core init.
static void nm_mem_fence(void)
memory fence only when multithread
void nm_core_req_monitor(struct nm_core *p_core, struct nm_req_s *p_req, struct nm_monitor_s monitor)
set a per-request monitor.
uint32_t nm_req_chunk_flag_t
flags for req_chunk
void nm_core_pack_set_priority(struct nm_core *p_core, struct nm_req_s *p_pack, nm_prio_t priority)
set a priority for the given pack request
static void nm_spin_unlock(nm_spinlock_t *p_spin)
release the spin lock
static void nm_status_add(struct nm_req_s *p_req, nm_status_t bitmask)
static void nm_status_wait(struct nm_req_s *p_req, nm_status_t bitmask, nm_core_t p_core)
wait for any bit matching in req status
static void nm_atomic_add(int *v, int v2)
int add, atomic only when multithread
static int nm_atomic_alway_inc(int *v)
increment int, always atomic
void nm_core_task_submit_locked(struct nm_core *p_core, void(*p_handler)(void))
lock then submit task to pending list
static nm_status_t nm_status_test(const struct nm_req_s *p_req, nm_status_t bitmask)
query for given bits in req status; returns matched bits
static void nm_status_assert(struct nm_req_s *p_req __attribute__((unused)), nm_status_t value __attribute__((unused)))
int nm_core_init(nm_core_t *pp_core)
void nm_core_gate_connect_wait(nm_core_t p_core, struct nm_trk_s *p_trk)
wait for connection completion
void nm_core_monitor_remove(nm_core_t p_core, struct nm_core_monitor_s *m)
Unregister an event monitor.
nm_seq_t nm_core_send_seq_get(struct nm_core *p_core, nm_gate_t p_gate, nm_core_tag_t tag)
get a seq number in the out stream, to route packet outside of nmad core
void nm_core_gate_connect_async(nm_core_t p_core, nm_gate_t gate, nm_drv_t p_drv, nm_trk_id_t trk_id, const char *url)
start connection process on given gate/trk
void nm_core_pack_submit_chunks(struct nm_core *p_core, struct nm_req_s *p_pack, int n, const struct nm_chunk_s *p_chunks)
@ NM_CORE_TASK_COMPLETED_PREFETCH
prefetch completed; process RTR if received
@ NM_CORE_TASK_UNPACK_NEXT
try to match the next unpack on the given gate/tag/gtag
@ NM_CORE_TASK_RTR_SEND
send a RTR once the large pw for recv has been posted
@ NM_CORE_TASK_PACK_SUBMISSION
process a submitted pack request
@ NM_CORE_TASK_NONE
@ NM_CORE_TASK_COMPLETED_PW
process a completed pw
@ NM_CORE_TASK_HANDLER
call a user handler, mainly for testing/benchmarking
@ NM_THREAD_FUNNELED
@ NM_THREAD_SINGLE
@ NM_THREAD_MULTIPLE
@ NM_THREAD_SERIALIZED
static void nm_cond_init(nm_cond_status_t *p_cond, nm_status_t bitmask)
initialize a nm_cond_status_t object
static nm_status_t nm_cond_test(const nm_cond_status_t *p_cond, nm_status_t bitmask)
test whether the given bit is set in the status; unlocked, weak consistency
static void nm_cond_add(nm_cond_status_t *p_cond, nm_status_t bitmask)
add a bit to the bitmask in the status, do not unlock waiters (for bits that will not be waited for)
static void nm_cond_wait_all(void **pp_conds, int n, uintptr_t offset, nm_status_t bitmask, nm_core_t p_core)
wait on multiple statuses at the same time
static void nm_cond_signal(nm_cond_status_t *p_cond, nm_status_t bitmask)
add a bit and wake up threads waiting for it
static nm_status_t nm_cond_test_locked(const nm_cond_status_t *p_cond, nm_status_t bitmask)
test whether the given bit is set in the status; locked, guaranteed consistency, slower
static void nm_cond_wait(nm_cond_status_t *p_cond, nm_status_t bitmask, nm_core_t p_core)
wait for the given bit to be set in the status; do active polling while waiting
static void nm_cond_destroy(nm_cond_status_t *p_cond)
free resources associated with a nm_cond_status_t object
nm_session_hash_t hashcode
the session hashcode
nm_tag_t tag
the user-supplied tag
static nm_gate_t p_gate
nm_prio_t priority
Definition: nm_headers.h:6
uint16_t hlen
length in header (header + data in header)
Definition: nm_headers.h:5
nm_len_t chunk_len
length of this chunk
Definition: nm_headers.h:4
nm_trk_id_t trk_id
index of the track relative to the gate
Definition: nm_headers.h:3
nm_len_t chunk_offset
offset of the enclosed chunk
Definition: nm_headers.h:4
nm_seq_t seq
sequence number
Definition: nm_headers.h:2
Basic primitives to display info & warnings.
#define NM_FATAL(format,...)
Definition: nm_log.h:36
#define NM_WARN(format,...)
Definition: nm_log.h:34
nm_gate_t gate
gate of the destination or the source node
nm_mpi_status_t status
status of request
Definition: nm_mpi_private.h:7
nm_onesided_flag_t flags
This is the common public header for NewMad.
int8_t nm_trk_id_t
ID of a track, assigned in order.
Definition: nm_types.h:88
uint64_t nm_req_seq_t
sequence number for requests
Definition: nm_types.h:113
int32_t nm_prio_t
message priority
Definition: nm_types.h:80
uint64_t nm_tag_t
user tags, 64 bits, contained in indirect hashtable
Definition: nm_types.h:58
uint64_t nm_len_t
data length used by nmad
Definition: nm_types.h:70
uint32_t nm_seq_t
Sequence number for packets on a given gate/tag.
Definition: nm_types.h:104
uint8_t nm_proto_t
protocol flags- not part of the public API, but needed for inline
Definition: nm_types.h:101
enum nm_trk_kind_e nm_trk_kind_t
nm_len_t chunk_len
nm_len_t chunk_offset
matching info for global monitors
nm_core_tag_t tag_mask
the mask to apply before comparing tags (only bits set in mask will be checked)
nm_core_tag_t tag
the tag to listen too
nm_gate_t p_gate
the gate to listen to, or NM_ANY_GATE for any
An event, generated by the NewMad core.
struct nm_req_s * p_req
the request that matched the event- NULL in case of unexpected packets
nm_core_tag_t tag
nm_status_t status
status flags- describe the event
exposed here for inlining; do not use this value, use the accessor nm_core_get_singleton()
global monitor for status transitions
struct nm_monitor_s monitor
the monitor to fire upon matching event
struct nm_core_event_matching_s matching
packet matching information
An internal tag.
nm_tag_t tag
the user-supplied tag
nm_session_hash_t hashcode
the session hashcode
asynchronous tasks for nmad core.
struct nm_core_task_s::@11::@17 handler
struct nm_core_task_s::@11::@13 completed_pw
void(* p_handler)(void)
enum nm_core_task_kind_e kind
struct nm_core_task_s::@11::@16 rtr_send
struct nm_core_task_s::@11::@12 unpack_next
union nm_core_task_s::@11 content
struct nm_pkt_wrap_s * p_pw
struct nm_core_task_s::@11::@15 pack_submission
struct nm_matching_container_s matching
struct nm_req_chunk_s * p_req_chunk
struct nm_core_task_s::@11::@14 completed_prefetch
Core NewMadeleine structure.
Definition: nm_core.h:39
block of static properties for a given data descriptor
Definition: nm_data.h:163
a data descriptor, used to pack/unpack data from app layout to/from contiguous buffers
Definition: nm_data.h:189
Driver.
Definition: nm_drv.h:29
struct nm_core * p_core
Definition: nm_drv.h:56
const char * url
driver url, as string
Definition: nm_drv.h:49
const struct nm_minidriver_iface_s * driver
Driver interface, for use when no instance is needed.
Definition: nm_drv.h:40
Connection to another process.
Definition: nm_gate.h:100
status of tags on each gate
Definition: nm_gate.h:22
containers for matching info, used for caching
struct nm_gtag_s * p_gtag
cache of gtag
struct nm_matching_gsession_s * p_gsession
cache of matching gsession
struct nm_matching_wildcard_s * p_wildcard
cache of matching wildcard
struct nm_matching_tag_s * p_matching_tag
cache of matching tag
struct to store matching info for any-source requests of a given tag
Definition: nm_tags.h:146
struct to store matching info for wildcard requests, one per session
Definition: nm_tags.h:126
generic monitor, used for requests and for global events (with matching)
nm_status_t event_mask
mask applied to status to check whether to fire events
nm_core_event_notifier_t p_notifier
notification function called to fire events
void * ref
opaque user-supplied pointer passed to notifier
Internal packet wrapper.
Definition: nm_pkt_wrap.h:117
a chunk of request
PUK_LIST_LINK(nm_req_chunk)
nm_len_t chunk_offset
offset of the chunk relative to the full data in the req
struct nm_core_task_s core_task
nm_proto_t proto_flags
pre-computed proto flags
struct nm_data_properties_s chunk_props
properties of the data chunk
nm_len_t chunk_len
length of the chunk
struct nm_req_s * p_req
link to insert the req chunk as a core task
a generic pack/unpack request
struct nm_req_s::@18::@21 unpack
nm_core_tag_t tag
tag to send to/from (works in combination with tag_mask for recv)
nm_len_t expected_len
length of posted recv (may be updated if matched packet is shorter)
PUK_LIST_LINK(nm_req)
link to enqueue req in pending requests lists
nm_gate_t p_gate
dest/src gate; NULL if recv from any source
struct nm_matching_container_s matching
link to store request in a matching map
nm_len_t done
cumulated length of data sent so far
nm_prio_t priority
request priority level
uint32_t checksum
data checkusm when pack was submitted- for debug only
struct nm_req_pchunk_s * p_next
struct nm_req_s::@18::@21::@22::nm_req_pchunk_s * p_pchunks
unsorted list of arrived chunks; reads are lock-free, writes are within core_core_lock sections
struct nm_gtag_s * p_gtag
cache for tag status on gate; NULL if tag or gate is unspecified yet
nm_len_t offset
offset of data partially received
nm_cond_status_t status
status, including status bits and synchronization
struct nm_req_s::@18::@21::@22 partition
partitioned unpack, used only if NM_REQ_FLAG_UNPACK_PARTITIONED is set
nm_req_seq_t req_seq
request sequence number used to interleave wildcard/non-wildcard requests
nm_len_t chunk_offset
struct nm_req_chunk_s req_chunk
preallocated chunk for the common case (single-chunk)
nm_req_flag_t flags
flags given by user
struct nm_data_s data
data descriptor to send/recv
struct nm_req_s::@18::@20 pack
struct nm_pkt_wrap_s * p_prefetch_pw
packet wrapper to prefetch recv
nm_core_tag_t tag_mask
mask applied to tag for matching (only bits in mask need to match)
nm_len_t cumulated_len
amount of data unpacked so far
nm_len_t len
cumulated data length
int err
error status of the request
struct nm_monitor_s monitor
monitor attached to this request (only 1)
nm_seq_t seq
packet sequence number on the given tag
nm_len_t chunk_len
nm_len_t hlen
length of header to send eagerly
a track on a given gate
Definition: nm_gate.h:64