/**************************************************************************** * sched/mqueue/msginternal.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include "mqueue/msg.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ #define MQ_PERBLOCK 10 /**************************************************************************** * Private Data ****************************************************************************/ static uint8_t g_nmsgq; /* The number of groups of msgs array */ static FAR struct msgq_s **g_msgqs; /* The pointer of two layer file descriptors array */ /**************************************************************************** * Public Data ****************************************************************************/ struct list_node g_msgfreelist = LIST_INITIAL_VALUE(g_msgfreelist); /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Name: nxmsg_alloc_internal ****************************************************************************/ static FAR struct msgq_s *nxmsg_alloc_internal(void) { FAR struct msgq_s *msgq; FAR struct msgq_s **tmp; int i; msgq = kmm_zalloc(sizeof(struct msgq_s)); if (msgq == NULL) { return NULL; } for (i = 0; i < g_nmsgq; i++) { if (g_msgqs[i] == NULL) { g_msgqs[i] = msgq; msgq->key = i + 1; return msgq; } } tmp = kmm_realloc(g_msgqs, sizeof(FAR void *) * (g_nmsgq + MQ_PERBLOCK)); if (tmp == NULL) { kmm_free(msgq); return NULL; } g_msgqs = tmp; memset(&g_msgqs[g_nmsgq], 0, sizeof(FAR void *) * MQ_PERBLOCK); g_msgqs[g_nmsgq] = msgq; msgq->key = g_nmsgq + 1; g_nmsgq += MQ_PERBLOCK; return msgq; } /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: nxmsg_initialize ****************************************************************************/ void nxmsg_initialize(void) { FAR struct msgbuf_s *msg; msg = (FAR struct msgbuf_s *)kmm_malloc(sizeof(*msg) * CONFIG_PREALLOC_MQ_MSGS); if (msg) { int i; for (i = 0; i < CONFIG_PREALLOC_MQ_MSGS; i++) { list_add_tail(&g_msgfreelist, &msg->node); msg++; } } } /**************************************************************************** * Name: nxmsg_alloc ****************************************************************************/ int nxmsg_alloc(FAR struct msgq_s **pmsgq) { FAR struct msgq_s *msgq; msgq = nxmsg_alloc_internal(); if (msgq == NULL) { return -ENOMEM; } /* Initialize the new named message queue */ list_initialize(&msgq->msglist); msgq->maxmsgs = MSG_MAX_MSGS; msgq->maxmsgsize = MSG_MAX_BYTES; *pmsgq = msgq; return OK; } /**************************************************************************** * Name: nxmsg_free ****************************************************************************/ void nxmsg_free(FAR struct msgq_s *msgq) { FAR struct msgbuf_s *entry; FAR struct msgbuf_s *tmp; int index; if (msgq == NULL || msgq->key <= 0 || msgq->key > g_nmsgq) { return; } index = msgq->key - 1; list_for_every_entry_safe(&msgq->msglist, entry, tmp, struct msgbuf_s, node) { list_delete(&entry->node); list_add_tail(&g_msgfreelist, &entry->node); } kmm_free(g_msgqs[index]); g_msgqs[index] = NULL; } /**************************************************************************** * Name: nxmsg_lookup ****************************************************************************/ FAR struct msgq_s *nxmsg_lookup(key_t key) { if (key <= 0 || key > g_nmsgq) { return NULL; } return g_msgqs[key - 1]; }