blob: ae84f4004b82b7df38bcc55789c7db4ec2a2e9c1 [file] [log] [blame]
// Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "msg.h"
#include "global.h"
#define msg_malloc(s) sdk_malloc(s)
#define msg_free(b) sdk_free(b)
#define MAX_MSG_POOL 10
void msg_init(msg_cb_t *msg_cb)
{
msg_cb->mc_msg_pool = NULL;
msg_cb->mc_head = NULL;
msg_cb->mc_tail = NULL;
msg_cb->mc_pool_cnt = 0;
pthread_mutex_init(&msg_cb->mc_lock, NULL);
pthread_cond_init(&msg_cb->mc_cond, NULL);
}
void msg_deinit(msg_cb_t *msg_cb)
{
int free_cnt = 0;
msg_t *msg;
pthread_mutex_lock(&msg_cb->mc_lock);
while (msg_cb->mc_msg_pool) {
msg = msg_cb->mc_msg_pool;
msg_cb->mc_msg_pool = msg_cb->mc_msg_pool->ms_next;
msg_free(msg);
free_cnt++;
}
msg_cb->mc_pool_cnt = 0;
pthread_mutex_unlock(&msg_cb->mc_lock);
pthread_mutex_destroy(&msg_cb->mc_lock);
pthread_cond_destroy(&msg_cb->mc_cond);
assert(free_cnt <= MAX_MSG_POOL);
}
static void put_msg_pool(msg_cb_t *msg_cb, msg_t *msg)
{
if (!msg_cb->mc_msg_pool) {
msg->ms_next = NULL;
msg_cb->mc_msg_pool = msg;
assert(msg_cb->mc_pool_cnt == 0);
}
else {
msg->ms_next = msg_cb->mc_msg_pool;
msg_cb->mc_msg_pool = msg;
assert(msg_cb->mc_pool_cnt > 0);
}
msg_cb->mc_pool_cnt++;
}
static msg_t *get_msg_pool(msg_cb_t *msg_cb)
{
msg_t *msg;
msg = msg_cb->mc_msg_pool;
msg_cb->mc_msg_pool = msg->ms_next;
msg_cb->mc_pool_cnt--;
assert(msg_cb->mc_pool_cnt >= 0);
return msg;
}
void msg_send(msg_cb_t *msg_cb, int prim, void *data)
{
msg_t *msg;
pthread_mutex_lock(&msg_cb->mc_lock);
if (!msg_cb->mc_msg_pool) {
pthread_mutex_unlock(&msg_cb->mc_lock);
msg = (msg_t *) msg_malloc(sizeof(msg_t));
assert(msg);
pthread_mutex_lock(&msg_cb->mc_lock);
}
else
msg = get_msg_pool(msg_cb);
msg->ms_prim = prim;
msg->ms_data = data;
msg->ms_next = NULL;
if (!msg_cb->mc_head)
msg_cb->mc_head = msg_cb->mc_tail = msg;
else {
msg_cb->mc_tail->ms_next = msg;
msg_cb->mc_tail = msg;
}
pthread_cond_signal(&msg_cb->mc_cond);
pthread_mutex_unlock(&msg_cb->mc_lock);
}
int msg_recv(msg_cb_t *msg_cb, int *prim, void **data)
{
msg_t *msg;
int ret = 0;
pthread_mutex_lock(&msg_cb->mc_lock);
if (!msg_cb->mc_head) {
ret = pthread_cond_wait(&msg_cb->mc_cond, &msg_cb->mc_lock);
assert(msg_cb->mc_head);
}
msg = msg_cb->mc_head;
msg_cb->mc_head = msg_cb->mc_head->ms_next;
if (prim)
*prim = msg->ms_prim;
if (data)
*data = msg->ms_data;
if (msg_cb->mc_pool_cnt < MAX_MSG_POOL) {
put_msg_pool(msg_cb, msg);
pthread_mutex_unlock(&msg_cb->mc_lock);
}
else {
pthread_mutex_unlock(&msg_cb->mc_lock);
msg_free(msg);
}
return ret;
}