mm_camera_thread.c revision b16c077cdee23becd2ec0c353b8edde1368a8001
1/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30#include <pthread.h> 31#include <errno.h> 32#include <sys/ioctl.h> 33#include <sys/types.h> 34#include <sys/stat.h> 35#include <sys/prctl.h> 36#include <fcntl.h> 37#include <poll.h> 38#include <cam_semaphore.h> 39 40#include "mm_camera_dbg.h" 41#include "mm_camera_interface.h" 42#include "mm_camera.h" 43 44typedef enum { 45 /* poll entries updated */ 46 MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED, 47 /* poll entries updated */ 48 MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC, 49 /* exit */ 50 MM_CAMERA_PIPE_CMD_EXIT, 51 /* max count */ 52 MM_CAMERA_PIPE_CMD_MAX 53} mm_camera_pipe_cmd_type_t; 54 55typedef enum { 56 MM_CAMERA_POLL_TASK_STATE_STOPPED, 57 MM_CAMERA_POLL_TASK_STATE_POLL, /* polling pid in polling state. */ 58 MM_CAMERA_POLL_TASK_STATE_MAX 59} mm_camera_poll_task_state_type_t; 60 61typedef struct { 62 uint8_t cmd; 63 mm_camera_event_t event; 64} mm_camera_sig_evt_t; 65 66 67/*=========================================================================== 68 * FUNCTION : mm_camera_poll_sig_async 69 * 70 * DESCRIPTION: Asynchoronous call to send a command through pipe. 71 * 72 * PARAMETERS : 73 * @poll_cb : ptr to poll thread object 74 * @cmd : command to be sent 75 * 76 * RETURN : int32_t type of status 77 * 0 -- success 78 * -1 -- failure 79 *==========================================================================*/ 80static int32_t mm_camera_poll_sig_async(mm_camera_poll_thread_t *poll_cb, 81 uint32_t cmd) 82{ 83 /* send through pipe */ 84 /* get the mutex */ 85 mm_camera_sig_evt_t cmd_evt; 86 int len; 87 88 CDBG("%s: E cmd = %d", __func__,cmd); 89 memset(&cmd_evt, 0, sizeof(cmd_evt)); 90 cmd_evt.cmd = cmd; 91 pthread_mutex_lock(&poll_cb->mutex); 92 /* reset the statue to false */ 93 poll_cb->status = FALSE; 94 /* send cmd to worker */ 95 96 len = write(poll_cb->pfds[1], &cmd_evt, sizeof(cmd_evt)); 97 if(len < 1) { 98 CDBG_ERROR("%s: len = %d, errno = %d", __func__, len, errno); 99 /* Avoid waiting for the signal */ 100 pthread_mutex_unlock(&poll_cb->mutex); 101 return 0; 102 } 103 CDBG("%s: begin IN mutex write done, len = %d", __func__, len); 104 pthread_mutex_unlock(&poll_cb->mutex); 105 CDBG("%s: X", __func__); 106 return 0; 107} 108 109 110 111 112/*=========================================================================== 113 * FUNCTION : mm_camera_poll_sig 114 * 115 * DESCRIPTION: synchorinzed call to send a command through pipe. 116 * 117 * PARAMETERS : 118 * @poll_cb : ptr to poll thread object 119 * @cmd : command to be sent 120 * 121 * RETURN : int32_t type of status 122 * 0 -- success 123 * -1 -- failure 124 *==========================================================================*/ 125static int32_t mm_camera_poll_sig(mm_camera_poll_thread_t *poll_cb, 126 uint32_t cmd) 127{ 128 /* send through pipe */ 129 /* get the mutex */ 130 mm_camera_sig_evt_t cmd_evt; 131 int len; 132 133 CDBG("%s: E cmd = %d", __func__,cmd); 134 memset(&cmd_evt, 0, sizeof(cmd_evt)); 135 cmd_evt.cmd = cmd; 136 pthread_mutex_lock(&poll_cb->mutex); 137 /* reset the statue to false */ 138 poll_cb->status = FALSE; 139 /* send cmd to worker */ 140 141 len = write(poll_cb->pfds[1], &cmd_evt, sizeof(cmd_evt)); 142 if(len < 1) { 143 CDBG_ERROR("%s: len = %d, errno = %d", __func__, len, errno); 144 /* Avoid waiting for the signal */ 145 pthread_mutex_unlock(&poll_cb->mutex); 146 return 0; 147 } 148 CDBG("%s: begin IN mutex write done, len = %d", __func__, len); 149 /* wait till worker task gives positive signal */ 150 if (FALSE == poll_cb->status) { 151 CDBG("%s: wait", __func__); 152 pthread_cond_wait(&poll_cb->cond_v, &poll_cb->mutex); 153 } 154 /* done */ 155 pthread_mutex_unlock(&poll_cb->mutex); 156 CDBG("%s: X", __func__); 157 return 0; 158} 159 160/*=========================================================================== 161 * FUNCTION : mm_camera_poll_sig 162 * 163 * DESCRIPTION: signal the status of done 164 * 165 * PARAMETERS : 166 * @poll_cb : ptr to poll thread object 167 * 168 * RETURN : none 169 *==========================================================================*/ 170static void mm_camera_poll_sig_done(mm_camera_poll_thread_t *poll_cb) 171{ 172 pthread_mutex_lock(&poll_cb->mutex); 173 poll_cb->status = TRUE; 174 pthread_cond_signal(&poll_cb->cond_v); 175 CDBG("%s: done, in mutex", __func__); 176 pthread_mutex_unlock(&poll_cb->mutex); 177} 178 179/*=========================================================================== 180 * FUNCTION : mm_camera_poll_set_state 181 * 182 * DESCRIPTION: set a polling state 183 * 184 * PARAMETERS : 185 * @poll_cb : ptr to poll thread object 186 * @state : polling state (stopped/polling) 187 * 188 * RETURN : none 189 *==========================================================================*/ 190static void mm_camera_poll_set_state(mm_camera_poll_thread_t *poll_cb, 191 mm_camera_poll_task_state_type_t state) 192{ 193 poll_cb->state = state; 194} 195 196/*=========================================================================== 197 * FUNCTION : mm_camera_poll_proc_pipe 198 * 199 * DESCRIPTION: polling thread routine to process pipe 200 * 201 * PARAMETERS : 202 * @poll_cb : ptr to poll thread object 203 * 204 * RETURN : none 205 *==========================================================================*/ 206static void mm_camera_poll_proc_pipe(mm_camera_poll_thread_t *poll_cb) 207{ 208 ssize_t read_len; 209 int i; 210 mm_camera_sig_evt_t cmd_evt; 211 read_len = read(poll_cb->pfds[0], &cmd_evt, sizeof(cmd_evt)); 212 CDBG("%s: read_fd = %d, read_len = %d, expect_len = %d cmd = %d", 213 __func__, poll_cb->pfds[0], (int)read_len, (int)sizeof(cmd_evt), cmd_evt.cmd); 214 switch (cmd_evt.cmd) { 215 case MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED: 216 case MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC: 217 /* we always have index 0 for pipe read */ 218 poll_cb->num_fds = 0; 219 poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->pfds[0]; 220 poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI; 221 poll_cb->num_fds++; 222 223 if (MM_CAMERA_POLL_TYPE_EVT == poll_cb->poll_type) { 224 if (poll_cb->poll_entries[0].fd > 0) { 225 /* fd is valid, we update poll_fds */ 226 poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[0].fd; 227 poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI; 228 poll_cb->num_fds++; 229 } 230 } else if (MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) { 231 for(i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 232 if(poll_cb->poll_entries[i].fd > 0) { 233 /* fd is valid, we update poll_fds to this fd */ 234 poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[i].fd; 235 poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI; 236 poll_cb->num_fds++; 237 } else { 238 /* fd is invalid, we set the entry to -1 to prevent polling. 239 * According to spec, polling will not poll on entry with fd=-1. 240 * If this is not the case, we need to skip these invalid fds 241 * when updating this array. 242 * We still keep fd=-1 in this array because this makes easier to 243 * map cb associated with this fd once incoming data avail by directly 244 * using the index-1(0 is reserved for pipe read, so need to reduce index by 1) */ 245 poll_cb->poll_fds[poll_cb->num_fds].fd = -1; 246 poll_cb->poll_fds[poll_cb->num_fds].events = 0; 247 poll_cb->num_fds++; 248 } 249 } 250 } 251 if (cmd_evt.cmd != MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC) 252 mm_camera_poll_sig_done(poll_cb); 253 break; 254 255 case MM_CAMERA_PIPE_CMD_EXIT: 256 default: 257 mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_STOPPED); 258 mm_camera_poll_sig_done(poll_cb); 259 break; 260 } 261} 262 263/*=========================================================================== 264 * FUNCTION : mm_camera_poll_fn 265 * 266 * DESCRIPTION: polling thread routine 267 * 268 * PARAMETERS : 269 * @poll_cb : ptr to poll thread object 270 * 271 * RETURN : none 272 *==========================================================================*/ 273static void *mm_camera_poll_fn(mm_camera_poll_thread_t *poll_cb) 274{ 275 int rc = 0, i; 276 277 CDBG("%s: poll type = %d, num_fd = %d poll_cb = %p\n", 278 __func__, poll_cb->poll_type, poll_cb->num_fds,poll_cb); 279 do { 280 for(i = 0; i < poll_cb->num_fds; i++) { 281 poll_cb->poll_fds[i].events = POLLIN|POLLRDNORM|POLLPRI; 282 } 283 284 rc = poll(poll_cb->poll_fds, poll_cb->num_fds, poll_cb->timeoutms); 285 if(rc > 0) { 286 if ((poll_cb->poll_fds[0].revents & POLLIN) && 287 (poll_cb->poll_fds[0].revents & POLLRDNORM)) { 288 /* if we have data on pipe, we only process pipe in this iteration */ 289 CDBG("%s: cmd received on pipe\n", __func__); 290 mm_camera_poll_proc_pipe(poll_cb); 291 } else { 292 for(i=1; i<poll_cb->num_fds; i++) { 293 /* Checking for ctrl events */ 294 if ((poll_cb->poll_type == MM_CAMERA_POLL_TYPE_EVT) && 295 (poll_cb->poll_fds[i].revents & POLLPRI)) { 296 CDBG("%s: mm_camera_evt_notify\n", __func__); 297 if (NULL != poll_cb->poll_entries[i-1].notify_cb) { 298 poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data); 299 } 300 } 301 302 if ((MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) && 303 (poll_cb->poll_fds[i].revents & POLLIN) && 304 (poll_cb->poll_fds[i].revents & POLLRDNORM)) { 305 CDBG("%s: mm_stream_data_notify\n", __func__); 306 if (NULL != poll_cb->poll_entries[i-1].notify_cb) { 307 poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data); 308 } 309 } 310 } 311 } 312 } else { 313 /* in error case sleep 10 us and then continue. hard coded here */ 314 usleep(10); 315 continue; 316 } 317 } while (poll_cb->state == MM_CAMERA_POLL_TASK_STATE_POLL); 318 return NULL; 319} 320 321/*=========================================================================== 322 * FUNCTION : mm_camera_poll_thread 323 * 324 * DESCRIPTION: polling thread entry function 325 * 326 * PARAMETERS : 327 * @data : ptr to poll thread object 328 * 329 * RETURN : none 330 *==========================================================================*/ 331static void *mm_camera_poll_thread(void *data) 332{ 333 prctl(PR_SET_NAME, (unsigned long)"mm_cam_poll_th", 0, 0, 0); 334 mm_camera_poll_thread_t *poll_cb = (mm_camera_poll_thread_t *)data; 335 336 /* add pipe read fd into poll first */ 337 poll_cb->poll_fds[poll_cb->num_fds++].fd = poll_cb->pfds[0]; 338 339 mm_camera_poll_sig_done(poll_cb); 340 mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_POLL); 341 return mm_camera_poll_fn(poll_cb); 342} 343 344/*=========================================================================== 345 * FUNCTION : mm_camera_poll_thread 346 * 347 * DESCRIPTION: notify the polling thread that entries for polling fd have 348 * been updated 349 * 350 * PARAMETERS : 351 * @poll_cb : ptr to poll thread object 352 * 353 * RETURN : none 354 *==========================================================================*/ 355int32_t mm_camera_poll_thread_notify_entries_updated(mm_camera_poll_thread_t * poll_cb) 356{ 357 /* send poll entries updated signal to poll thread */ 358 return mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED); 359} 360 361/*=========================================================================== 362 * FUNCTION : mm_camera_poll_thread_add_poll_fd 363 * 364 * DESCRIPTION: add a new fd into polling thread 365 * 366 * PARAMETERS : 367 * @poll_cb : ptr to poll thread object 368 * @handler : stream handle if channel data polling thread, 369 * 0 if event polling thread 370 * @fd : file descriptor need to be added into polling thread 371 * @notify_cb : callback function to handle if any notify from fd 372 * @userdata : user data ptr 373 * 374 * RETURN : none 375 *==========================================================================*/ 376int32_t mm_camera_poll_thread_add_poll_fd(mm_camera_poll_thread_t * poll_cb, 377 uint32_t handler, 378 int32_t fd, 379 mm_camera_poll_notify_t notify_cb, 380 void* userdata) 381{ 382 int32_t rc = -1; 383 uint8_t idx = 0; 384 385 if (MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) { 386 /* get stream idx from handler if CH type */ 387 idx = mm_camera_util_get_index_by_handler(handler); 388 } else { 389 /* for EVT type, only idx=0 is valid */ 390 idx = 0; 391 } 392 393 if (MAX_STREAM_NUM_IN_BUNDLE > idx) { 394 poll_cb->poll_entries[idx].fd = fd; 395 poll_cb->poll_entries[idx].handler = handler; 396 poll_cb->poll_entries[idx].notify_cb = notify_cb; 397 poll_cb->poll_entries[idx].user_data = userdata; 398 /* send poll entries updated signal to poll thread */ 399 rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED); 400 } else { 401 CDBG_ERROR("%s: invalid handler %d (%d)", 402 __func__, handler, idx); 403 } 404 return rc; 405} 406 407/*=========================================================================== 408 * FUNCTION : mm_camera_poll_thread_del_poll_fd 409 * 410 * DESCRIPTION: delete a fd from polling thread 411 * 412 * PARAMETERS : 413 * @poll_cb : ptr to poll thread object 414 * @handler : stream handle if channel data polling thread, 415 * 0 if event polling thread 416 * 417 * RETURN : none 418 *==========================================================================*/ 419int32_t mm_camera_poll_thread_del_poll_fd(mm_camera_poll_thread_t * poll_cb, 420 uint32_t handler, 421 mm_camera_call_type_t call_type) 422{ 423 int32_t rc = -1; 424 uint8_t idx = 0; 425 426 if (MM_CAMERA_POLL_TYPE_DATA == poll_cb->poll_type) { 427 /* get stream idx from handler if CH type */ 428 idx = mm_camera_util_get_index_by_handler(handler); 429 } else { 430 /* for EVT type, only idx=0 is valid */ 431 idx = 0; 432 } 433 434 if ((MAX_STREAM_NUM_IN_BUNDLE > idx) && 435 (handler == poll_cb->poll_entries[idx].handler)) { 436 /* reset poll entry */ 437 poll_cb->poll_entries[idx].fd = -1; /* set fd to invalid */ 438 poll_cb->poll_entries[idx].handler = 0; 439 poll_cb->poll_entries[idx].notify_cb = NULL; 440 441 /* send poll entries updated signal to poll thread */ 442 if (call_type == mm_camera_sync_call ) { 443 rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED); 444 } else { 445 rc = mm_camera_poll_sig_async(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC ); 446 } 447 } else { 448 CDBG_ERROR("%s: invalid handler %d (%d)", 449 __func__, handler, idx); 450 } 451 452 return rc; 453} 454 455static pthread_mutex_t constr_destr_lock = PTHREAD_MUTEX_INITIALIZER; 456 457int32_t mm_camera_poll_thread_launch(mm_camera_poll_thread_t * poll_cb, 458 mm_camera_poll_thread_type_t poll_type) 459{ 460 int32_t rc = 0; 461 462 pthread_mutex_lock(&constr_destr_lock); 463 464 poll_cb->poll_type = poll_type; 465 466 poll_cb->pfds[0] = 0; 467 poll_cb->pfds[1] = 0; 468 rc = pipe(poll_cb->pfds); 469 if(rc < 0) { 470 CDBG_ERROR("%s: pipe open rc=%d\n", __func__, rc); 471 pthread_mutex_unlock(&constr_destr_lock); 472 return -1; 473 } 474 475 poll_cb->timeoutms = -1; /* Infinite seconds */ 476 477 CDBG("%s: poll_type = %d, read fd = %d, write fd = %d timeout = %d", 478 __func__, poll_cb->poll_type, 479 poll_cb->pfds[0], poll_cb->pfds[1],poll_cb->timeoutms); 480 481 pthread_mutex_init(&poll_cb->mutex, NULL); 482 pthread_cond_init(&poll_cb->cond_v, NULL); 483 484 /* launch the thread */ 485 pthread_mutex_lock(&poll_cb->mutex); 486 poll_cb->status = 0; 487 pthread_create(&poll_cb->pid, NULL, mm_camera_poll_thread, (void *)poll_cb); 488 if(!poll_cb->status) { 489 pthread_cond_wait(&poll_cb->cond_v, &poll_cb->mutex); 490 } 491 pthread_mutex_unlock(&poll_cb->mutex); 492 CDBG("%s: End",__func__); 493 pthread_mutex_unlock(&constr_destr_lock); 494 return rc; 495} 496 497int32_t mm_camera_poll_thread_release(mm_camera_poll_thread_t *poll_cb) 498{ 499 int32_t rc = 0; 500 501 pthread_mutex_lock(&constr_destr_lock); 502 503 if(MM_CAMERA_POLL_TASK_STATE_STOPPED == poll_cb->state) { 504 CDBG_ERROR("%s: err, poll thread is not running.\n", __func__); 505 goto done; 506 } 507 508 /* send exit signal to poll thread */ 509 mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_EXIT); 510 /* wait until poll thread exits */ 511 if (pthread_join(poll_cb->pid, NULL) != 0) { 512 CDBG_ERROR("%s: pthread dead already\n", __func__); 513 } 514 515 /* close pipe */ 516 if(poll_cb->pfds[0]) { 517 close(poll_cb->pfds[0]); 518 } 519 if(poll_cb->pfds[1]) { 520 close(poll_cb->pfds[1]); 521 } 522 523 pthread_mutex_destroy(&poll_cb->mutex); 524 pthread_cond_destroy(&poll_cb->cond_v); 525 memset(poll_cb, 0, sizeof(mm_camera_poll_thread_t)); 526done: 527 pthread_mutex_unlock(&constr_destr_lock); 528 return rc; 529} 530 531static void *mm_camera_cmd_thread(void *data) 532{ 533 int running = 1; 534 int ret; 535 mm_camera_cmd_thread_t *cmd_thread = 536 (mm_camera_cmd_thread_t *)data; 537 mm_camera_cmdcb_t* node = NULL; 538 539 do { 540 do { 541 ret = cam_sem_wait(&cmd_thread->cmd_sem); 542 if (ret != 0 && errno != EINVAL) { 543 CDBG_ERROR("%s: cam_sem_wait error (%s)", 544 __func__, strerror(errno)); 545 return NULL; 546 } 547 } while (ret != 0); 548 549 /* we got notified about new cmd avail in cmd queue */ 550 node = (mm_camera_cmdcb_t*)cam_queue_deq(&cmd_thread->cmd_queue); 551 while (node != NULL) { 552 switch (node->cmd_type) { 553 case MM_CAMERA_CMD_TYPE_EVT_CB: 554 case MM_CAMERA_CMD_TYPE_DATA_CB: 555 case MM_CAMERA_CMD_TYPE_REQ_DATA_CB: 556 case MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB: 557 case MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY: 558 case MM_CAMERA_CMD_TYPE_FLUSH_QUEUE: 559 if (NULL != cmd_thread->cb) { 560 cmd_thread->cb(node, cmd_thread->user_data); 561 } 562 break; 563 case MM_CAMERA_CMD_TYPE_EXIT: 564 default: 565 running = 0; 566 break; 567 } 568 free(node); 569 node = (mm_camera_cmdcb_t*)cam_queue_deq(&cmd_thread->cmd_queue); 570 } /* (node != NULL) */ 571 } while (running); 572 return NULL; 573} 574 575int32_t mm_camera_cmd_thread_launch(mm_camera_cmd_thread_t * cmd_thread, 576 mm_camera_cmd_cb_t cb, 577 void* user_data) 578{ 579 int32_t rc = 0; 580 581 cam_sem_init(&cmd_thread->cmd_sem, 0); 582 cam_queue_init(&cmd_thread->cmd_queue); 583 cmd_thread->cb = cb; 584 cmd_thread->user_data = user_data; 585 586 /* launch the thread */ 587 pthread_create(&cmd_thread->cmd_pid, 588 NULL, 589 mm_camera_cmd_thread, 590 (void *)cmd_thread); 591 return rc; 592} 593 594int32_t mm_camera_cmd_thread_name(const char* name) 595{ 596 int32_t rc = 0; 597 /* name the thread */ 598 prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); 599 return rc; 600} 601 602 603int32_t mm_camera_cmd_thread_stop(mm_camera_cmd_thread_t * cmd_thread) 604{ 605 int32_t rc = 0; 606 mm_camera_cmdcb_t* node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 607 if (NULL == node) { 608 CDBG_ERROR("%s: No memory for mm_camera_cmdcb_t", __func__); 609 return -1; 610 } 611 612 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 613 node->cmd_type = MM_CAMERA_CMD_TYPE_EXIT; 614 615 cam_queue_enq(&cmd_thread->cmd_queue, node); 616 cam_sem_post(&cmd_thread->cmd_sem); 617 618 /* wait until cmd thread exits */ 619 if (pthread_join(cmd_thread->cmd_pid, NULL) != 0) { 620 CDBG("%s: pthread dead already\n", __func__); 621 } 622 return rc; 623} 624 625int32_t mm_camera_cmd_thread_destroy(mm_camera_cmd_thread_t * cmd_thread) 626{ 627 int32_t rc = 0; 628 cam_queue_deinit(&cmd_thread->cmd_queue); 629 cam_sem_destroy(&cmd_thread->cmd_sem); 630 memset(cmd_thread, 0, sizeof(mm_camera_cmd_thread_t)); 631 return rc; 632} 633 634int32_t mm_camera_cmd_thread_release(mm_camera_cmd_thread_t * cmd_thread) 635{ 636 int32_t rc = 0; 637 rc = mm_camera_cmd_thread_stop(cmd_thread); 638 if (0 == rc) { 639 rc = mm_camera_cmd_thread_destroy(cmd_thread); 640 } 641 return rc; 642} 643