You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
4.7 KiB
158 lines
4.7 KiB
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
* Copyright (C) 2016 Mopria Alliance, Inc.
|
|
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
|
|
*
|
|
* Licensed 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.
|
|
*/
|
|
|
|
#ifndef _GNU_SOURCE
|
|
#define _GNU_SOURCE
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <pthread.h>
|
|
#include <semaphore.h>
|
|
|
|
#include "wprint_msgq.h"
|
|
#include "wprint_debug.h"
|
|
|
|
#define TAG "wprint_msgq"
|
|
|
|
#define _SEM_NAME_LENGTH 16
|
|
|
|
typedef struct {
|
|
msg_q_id msgq_id;
|
|
char name[_SEM_NAME_LENGTH];
|
|
int max_msgs;
|
|
int max_msg_length;
|
|
int num_msgs;
|
|
sem_t sem_count;
|
|
sem_t *sem_ptr;
|
|
pthread_mutex_t mutex;
|
|
pthread_mutexattr_t mutexattr;
|
|
unsigned long read_offset;
|
|
unsigned long write_offset;
|
|
} _msgq_hdr_t;
|
|
|
|
msg_q_id msgQCreate(int max_msgs, int max_msg_length) {
|
|
_msgq_hdr_t *msgq;
|
|
int msgq_size;
|
|
|
|
msgq_size = sizeof(_msgq_hdr_t) + max_msgs * max_msg_length;
|
|
msgq = (_msgq_hdr_t *) malloc((size_t)msgq_size);
|
|
|
|
if (msgq) {
|
|
memset((char *) msgq, 0, (size_t)msgq_size);
|
|
msgq->msgq_id = (msg_q_id) msgq;
|
|
msgq->max_msgs = max_msgs;
|
|
msgq->max_msg_length = max_msg_length;
|
|
msgq->num_msgs = 0;
|
|
|
|
// create a mutex to protect access to this structure
|
|
pthread_mutexattr_init(&(msgq->mutexattr));
|
|
pthread_mutexattr_settype(&(msgq->mutexattr), PTHREAD_MUTEX_RECURSIVE_NP);
|
|
pthread_mutex_init(&msgq->mutex, &msgq->mutexattr);
|
|
|
|
// create a counting semaphore
|
|
msgq->sem_ptr = &msgq->sem_count;
|
|
sem_init(msgq->sem_ptr, 0, 0); // PRIVATE, EMPTY
|
|
|
|
msgq->read_offset = 0;
|
|
msgq->write_offset = 0;
|
|
}
|
|
return ((msg_q_id) msgq);
|
|
}
|
|
|
|
status_t msgQDelete(msg_q_id msgQ) {
|
|
_msgq_hdr_t *msgq = (msg_q_id) msgQ;
|
|
|
|
if (msgq) {
|
|
pthread_mutex_lock(&(msgq->mutex));
|
|
if (msgq->num_msgs) {
|
|
LOGE("Warning msgQDelete() called on queue with %d messages", msgq->num_msgs);
|
|
}
|
|
|
|
sem_destroy(&(msgq->sem_count));
|
|
pthread_mutex_unlock(&(msgq->mutex));
|
|
pthread_mutex_destroy(&(msgq->mutex));
|
|
free((void *) msgq);
|
|
}
|
|
return (msgq ? OK : ERROR);
|
|
}
|
|
|
|
status_t msgQSend(msg_q_id msgQ, const char *buffer, unsigned long nbytes, int timeout,
|
|
int priority) {
|
|
_msgq_hdr_t *msgq = (msg_q_id) msgQ;
|
|
char *msg_loc;
|
|
status_t result = ERROR;
|
|
|
|
// validate function arguments
|
|
if (msgq && (timeout == NO_WAIT) && (priority == MSG_Q_FIFO)) {
|
|
pthread_mutex_lock(&(msgq->mutex));
|
|
|
|
// ensure the message conforms to size limits and there is room in the msgQ
|
|
if ((nbytes <= msgq->max_msg_length) && (msgq->num_msgs < msgq->max_msgs)) {
|
|
msg_loc = (char *) msgq + sizeof(_msgq_hdr_t) +
|
|
(msgq->write_offset * msgq->max_msg_length);
|
|
memcpy(msg_loc, buffer, nbytes);
|
|
msgq->write_offset = (msgq->write_offset + 1) % msgq->max_msgs;
|
|
msgq->num_msgs++;
|
|
sem_post(msgq->sem_ptr);
|
|
result = OK;
|
|
}
|
|
|
|
pthread_mutex_unlock(&(msgq->mutex));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
status_t msgQReceive(msg_q_id msgQ, char *buffer, unsigned long max_nbytes, int timeout) {
|
|
_msgq_hdr_t *msgq = (msg_q_id) msgQ;
|
|
char *msg_loc;
|
|
status_t result = ERROR;
|
|
|
|
if (msgq && buffer && ((timeout == WAIT_FOREVER) || (timeout == NO_WAIT))) {
|
|
if (timeout == WAIT_FOREVER) {
|
|
result = (status_t) sem_wait(msgq->sem_ptr);
|
|
} else {
|
|
/* timeout is NO_WAIT */
|
|
result = (status_t) sem_trywait(msgq->sem_ptr);
|
|
}
|
|
|
|
if (result == 0) {
|
|
pthread_mutex_lock(&(msgq->mutex));
|
|
|
|
msg_loc = (char *) msgq + sizeof(_msgq_hdr_t) +
|
|
(msgq->read_offset * msgq->max_msg_length);
|
|
memcpy(buffer, msg_loc, max_nbytes);
|
|
msgq->read_offset = (msgq->read_offset + 1) % msgq->max_msgs;
|
|
msgq->num_msgs--;
|
|
pthread_mutex_unlock(&(msgq->mutex));
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int msgQNumMsgs(msg_q_id msgQ) {
|
|
_msgq_hdr_t *msgq = (msg_q_id) msgQ;
|
|
int num_msgs = -1;
|
|
|
|
if (msgq) {
|
|
pthread_mutex_lock(&(msgq->mutex));
|
|
num_msgs = msgq->num_msgs;
|
|
pthread_mutex_unlock(&(msgq->mutex));
|
|
}
|
|
return num_msgs;
|
|
} |