-
Notifications
You must be signed in to change notification settings - Fork 32
/
msgchan.go
208 lines (160 loc) · 4.36 KB
/
msgchan.go
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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2022-2023 Intel Corporation
*/
package cne
/*
#include <cne_common.h>
#include <msgchan.h>
*/
import "C"
import (
"fmt"
"sync"
"unsafe"
)
// MsgChannel is the structure to hold information about the MsgChan
type MsgChannel struct {
name string // Name of the channel
mChan unsafe.Pointer // MsgChannel internal pointer
}
// MsgChannelInfo is the structure to hold information about a MsgChannel
type MsgChannelInfo struct {
RecvRing unsafe.Pointer // RecvRing pointer
SendRing unsafe.Pointer // SendRing pointer
ChildCount int // Number of children attached to this msgChan
SendCalls uint64 // Number of calls to send routine
SendCnt uint64 // Number of items sent in send routine
RecvCalls uint64 // Number of calls to recv routine
RecvCnt uint64 // Number of items received in recv routine
RecvTimeouts uint64 // Number of timeouts the receive routine had
}
var msgChannel map[string]*MsgChannel
var msgChanMu sync.Mutex
func init() {
msgChannel = make(map[string]*MsgChannel)
}
// NewMsgChannel creates a new MsgChannel object with the given name and size
func NewMsgChannel(name string, sz uint) (*MsgChannel, error) {
msgChanMu.Lock()
defer msgChanMu.Unlock()
mc := &MsgChannel{name: name}
cStr := C.CString(name)
defer C.free(unsafe.Pointer(cStr))
mc.mChan = C.mc_create(cStr, C.int(sz), C.uint(0))
if mc.mChan == nil {
return nil, fmt.Errorf("unable to create message channel")
}
msgChannel[name] = mc
return mc, nil
}
// Close the MsgChannel and release the resources
func (mc *MsgChannel) Close() error {
msgChanMu.Lock()
defer msgChanMu.Unlock()
if mc == nil {
return fmt.Errorf("MsgChannel is nil")
}
C.mc_destroy(mc.mChan)
delete(msgChannel, mc.name)
return nil
}
// Name for the message channel
// Returns the message channel string or empty if error
func (mc *MsgChannel) Name() string {
if mc == nil {
return ""
}
return mc.name
}
// Send object values on the msgChan
// Returns the number of objects sent
func (mc *MsgChannel) Send(objs []uintptr) int {
var cnt int = 0
if mc != nil {
cObjs := (*unsafe.Pointer)(unsafe.Pointer(&objs[0]))
cnt = int(C.mc_send(mc.mChan, cObjs, C.int(len(objs))))
}
return cnt
}
// Recv objs from the msgChan
func (mc *MsgChannel) Recv(objs []uintptr, timo uint64) int {
var cnt int = 0
if mc != nil {
cObjs := (*unsafe.Pointer)(unsafe.Pointer(&objs[0]))
cnt = int(C.mc_recv(mc.mChan, cObjs, C.int(len(objs)), C.ulong(timo)))
}
return cnt
}
// Lookup a msgchan by name and return MsgChannel pointer
func (mc *MsgChannel) Lookup(name string) *MsgChannel {
msgChanMu.Lock()
defer msgChanMu.Unlock()
if m, ok := msgChannel[name]; ok {
return m
}
return nil
}
// Size of the message channel structure and rings
func (mc *MsgChannel) Size() int {
if mc == nil {
return 0
}
return int(C.mc_size(mc.mChan, nil, nil))
}
// RecvFree is the number of free entries in the receive ring
// Return number of free entries or -1 on error
func (mc *MsgChannel) RecvFree() int {
if mc != nil {
var rcvFree C.int
if C.mc_size(mc.mChan, &rcvFree, nil) == -1 {
return -1
}
return int(rcvFree)
}
return -1
}
// SendFree is the number of free entries in the send ring
// Return number of free entries or -1 on error
func (mc *MsgChannel) SendFree() int {
if mc != nil {
var sndFree C.int
if C.mc_size(mc.mChan, nil, &sndFree) == -1 {
return -1
}
return int(sndFree)
}
return -1
}
// Info returns the msgchan information structure
func (mc *MsgChannel) Info() *MsgChannelInfo {
var mcInfo C.msgchan_info_t
if mc == nil {
return nil
}
if C.mc_info(mc.mChan, &mcInfo) == -1 {
return nil
}
info := &MsgChannelInfo{
RecvRing: mcInfo.recv_ring,
SendRing: mcInfo.send_ring,
ChildCount: int(mcInfo.child_count),
SendCalls: uint64(mcInfo.send_calls),
SendCnt: uint64(mcInfo.send_cnt),
RecvCalls: uint64(mcInfo.recv_calls),
RecvCnt: uint64(mcInfo.recv_cnt),
RecvTimeouts: uint64(mcInfo.recv_timeouts),
}
return info
}
// Pointers returns the recv and send ring pointers or nil on error
func (mc *MsgChannel) Pointers() (recv unsafe.Pointer, send unsafe.Pointer) {
if mc == nil {
return nil, nil
}
info := mc.Info()
if info == nil {
return nil, nil
}
recv, send = info.RecvRing, info.SendRing
return
}