OpenCores
URL https://opencores.org/ocsvn/funbase_ip_library/funbase_ip_library/trunk

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [TUT/] [ip.swp.api/] [openmcapi/] [1.0/] [libmcapi/] [shm/] [linux/] [shm_os.c] - Blame information for rev 145

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 145 lanttu
/*
2
 * Copyright (c) 2010, Mentor Graphics Corporation
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
 * POSSIBILITY OF SUCH DAMAGE.
28
 */
29
 
30
 
31
#include <mcapi.h>
32
#include "../shm.h"
33
#include "../shm_os.h"
34
 
35
#include <stdio.h>
36
#include <fcntl.h>
37
#include <errno.h>
38
#include <unistd.h>
39
#include <sys/types.h>
40
#include <sys/stat.h>
41
#include <sys/mman.h>
42
#include <sys/ioctl.h>
43
 
44
typedef uint32_t mcomm_core_t;
45
typedef uint32_t mcomm_mbox_t;
46
 
47
/* Specify the layout of the mailboxes in shared memory */
48
#define MCOMM_INIT       _IOW('*', 0, struct mcomm_init_device)
49
/* All values in bytes */
50
struct mcomm_init_device {
51
    mcomm_mbox_t nr_mboxes;
52
    uint32_t offset; /* Offset from base of shared memory to first mailbox */
53
    uint32_t mbox_size;
54
    uint32_t mbox_stride; /* Offset from mailbox N to mailbox N+1 */
55
};
56
 
57
/* Get hardware-defined number for the current core */
58
#define MCOMM_CPUID      _IOR('*', 1, mcomm_core_t)
59
 
60
/* Block until data is available for specified mailbox */
61
#define MCOMM_WAIT_READ  _IOW('*', 2, mcomm_mbox_t)
62
 
63
/* Notify the specified core that data has been made available to it */
64
#define MCOMM_NOTIFY     _IOW('*', 3, mcomm_core_t)
65
 
66
 
67
static pthread_t shm_rx_thread;
68
 
69
/* XXX must close mcomm_fd somewhere */
70
static int mcomm_fd;
71
static size_t shm_bytes;
72
 
73
#define MCOMM_DEVICE "/dev/mcomm0"
74
 
75
static size_t shm_linux_read_size(void)
76
{
77
    unsigned long size;
78
    FILE *f;
79
    int rc;
80
 
81
    f = fopen("/sys/devices/platform/mcomm.0/size", "r");
82
    if (!f)
83
        f = fopen("/sys/devices/mcomm.0/size", "r");
84
    if (!f)
85
        return errno;
86
 
87
    rc = fscanf(f, "%lx", &size);
88
    if (rc < 0)
89
        size = errno;
90
 
91
    fclose(f);
92
 
93
    return size;
94
}
95
 
96
mcapi_status_t openmcapi_shm_notify(mcapi_uint32_t unit_id,
97
                                    mcapi_uint32_t node_id)
98
{
99
    mcapi_status_t mcapi_status = MCAPI_SUCCESS;
100
    int rc;
101
 
102
    rc = ioctl(mcomm_fd, MCOMM_NOTIFY, &unit_id);
103
    if (rc)
104
        mcapi_status = MCAPI_OS_ERROR;
105
 
106
    return mcapi_status;
107
}
108
 
109
mcapi_uint32_t openmcapi_shm_schedunitid(void)
110
{
111
    mcapi_uint32_t core_id;
112
    int rc;
113
 
114
    rc = ioctl(mcomm_fd, MCOMM_CPUID, &core_id);
115
    if (rc)
116
        return MCAPI_OS_ERROR;
117
 
118
    return core_id;
119
}
120
 
121
static int shm_linux_wait_notify(mcapi_uint32_t unitId)
122
{
123
    return ioctl(mcomm_fd, MCOMM_WAIT_READ, &unitId);
124
}
125
 
126
static int shm_linux_init_device(int fd)
127
{
128
    struct mcomm_init_device args;
129
    struct _shm_drv_mgmt_struct_ *mgmt = NULL;
130
 
131
    args.nr_mboxes = CONFIG_SHM_NR_NODES;
132
    args.offset = (unsigned int)&mgmt->shm_queues[0].count;
133
    args.mbox_size = sizeof(mgmt->shm_queues[0].count);
134
    args.mbox_stride = (void *)&mgmt->shm_queues[1].count -
135
                       (void *)&mgmt->shm_queues[0].count;
136
 
137
    return ioctl(fd, MCOMM_INIT, &args);
138
}
139
 
140
void *openmcapi_shm_map(void)
141
{
142
    void *shm;
143
    int fd;
144
    int rc;
145
 
146
    shm_bytes = shm_linux_read_size();
147
    if (shm_bytes <= 0) {
148
        perror("read shared memory size");
149
        return NULL;
150
    }
151
 
152
    fd = open(MCOMM_DEVICE, O_RDWR);
153
    if (fd < 0) {
154
        perror("open " MCOMM_DEVICE);
155
        goto out1;
156
    }
157
 
158
    /* Get the new file descriptor for the initialized device. */
159
    rc = shm_linux_init_device(fd);
160
    if (rc < 0) {
161
        perror("couldn't initialize device");
162
        goto out2;
163
    }
164
 
165
    mcomm_fd = rc;
166
 
167
    shm = mmap(NULL, shm_bytes, PROT_READ|PROT_WRITE, MAP_SHARED, mcomm_fd, 0);
168
    if (shm == MAP_FAILED) {
169
        perror("mmap shared memory");
170
        goto out3;
171
    }
172
 
173
    /* Don't need the original fd around any more. */
174
    close(fd);
175
 
176
    return shm;
177
 
178
out3:
179
    close(mcomm_fd);
180
out2:
181
    close(fd);
182
out1:
183
    return NULL;
184
}
185
 
186
/* pthread cancellation is tricky.
187
 *
188
 * First, we need to ensure that if we're blocked in the kernel (ioctl),
189
 * pthread_cancel must send us a signal so we return to userspace to handle it.
190
 * This is accomplished with PTHREAD_CANCEL_ASYNCHRONOUS, without which glibc
191
 * would set some state and then happily wait for us to hit the next
192
 * cancellation point (see pthreads(7)). However, we wouldn't, because we'd
193
 * never wake from the kernel.
194
 *
195
 * Second, pthread_cancel() could be called any time outside the
196
 * PTHREAD_CANCEL_ASYNCHRONOUS section. Since we don't necessarily have any
197
 * cancellation points inside the loop (including the shm_poll() path), we must
198
 * manually check by calling pthread_testcancel().
199
 */
200
static void *mcapi_receive_thread(void *data)
201
{
202
    int rc;
203
    int canceltype;
204
 
205
    do {
206
        /* Manually check if we're already dead. */
207
        pthread_testcancel();
208
 
209
        /* Block until data for this node is available or we are canceled with
210
         * a signal. */
211
        pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &canceltype);
212
        rc = shm_linux_wait_notify(MCAPI_Node_ID);
213
        if (rc < 0) {
214
            perror("wait ioctl");
215
            break;
216
        }
217
        pthread_setcanceltype(canceltype, NULL);
218
 
219
        /* Obtain lock so we can safely manipulate the RX_Queue. */
220
        MCAPI_Lock_RX_Queue();
221
 
222
        /* Process the incoming data. */
223
        shm_poll();
224
 
225
        MCAPI_Unlock_RX_Queue(0);
226
 
227
    } while (1);
228
 
229
    printf("%s exiting!\n", __func__);
230
    return NULL;
231
}
232
 
233
/* Now that SM_Mgmt_Blk has been initialized, we can start the RX thread. */
234
mcapi_status_t openmcapi_shm_os_init(void)
235
{
236
    mcapi_status_t mcapi_status = MCAPI_SUCCESS;
237
    int rc;
238
 
239
    rc = pthread_create(&shm_rx_thread, NULL, mcapi_receive_thread, NULL);
240
    if (rc) {
241
        perror("couldn't create pthread");
242
        mcapi_status = MCAPI_OS_ERROR;
243
    }
244
 
245
    return mcapi_status;
246
}
247
 
248
/* Finalize the SM driver OS specific layer. */
249
mcapi_status_t openmcapi_shm_os_finalize(void)
250
{
251
    mcapi_status_t mcapi_status = MCAPI_SUCCESS;
252
    int rc;
253
 
254
    rc = pthread_cancel(shm_rx_thread);
255
    if (rc) {
256
        perror("couldn't cancel thread");
257
        mcapi_status = MCAPI_OS_ERROR;
258
    }
259
 
260
    /* Don't return until it's dead. */
261
    rc = pthread_join(shm_rx_thread, NULL);
262
    if (rc) {
263
        perror("couldn't joined canceled thread");
264
        mcapi_status = MCAPI_OS_ERROR;
265
    }
266
 
267
    return mcapi_status;
268
}
269
 
270
void openmcapi_shm_unmap(void *shm)
271
{
272
    munmap(shm, shm_bytes);
273
 
274
    close(mcomm_fd);
275
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.