blob: 9f12b4cd323c44964e3fdcb4ab7505605d958466 [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 2009-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19/************************************************************************************
20 *
21 * Filename: btif_sock_thread.c
22 *
23 * Description: socket select thread
24 *
25 *
26 ***********************************************************************************/
27
Marie Janssen49a86702015-07-08 11:48:57 -070028#define LOG_TAG "bt_btif_sock"
29
30#include "btif_sock_thread.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080031
Miao Chou10969122015-06-09 17:39:46 -070032#include <alloca.h>
33#include <ctype.h>
34#include <errno.h>
35#include <fcntl.h>
36#include <features.h>
37#include <pthread.h>
38#include <signal.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080039#include <stdio.h>
40#include <stdlib.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080041#include <string.h>
Miao Chou10969122015-06-09 17:39:46 -070042#include <sys/poll.h>
43#include <sys/select.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080044#include <sys/socket.h>
Miao Chou10969122015-06-09 17:39:46 -070045#include <sys/types.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080046#include <sys/un.h>
47#include <time.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080048#include <unistd.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080049
The Android Open Source Project5738f832012-12-12 16:00:35 -080050#include "bta_api.h"
Miao Chou10969122015-06-09 17:39:46 -070051#include "btif_common.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080052#include "btif_sock.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080053#include "btif_sock_util.h"
Miao Chou10969122015-06-09 17:39:46 -070054#include "btif_util.h"
55#include "osi/include/socket_utils/sockets.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080056
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -070057#define asrt(s) if(!(s)) APPL_TRACE_ERROR("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__)
The Android Open Source Project5738f832012-12-12 16:00:35 -080058#define print_events(events) do { \
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -070059 APPL_TRACE_DEBUG("print poll event:%x", events); \
60 if (events & POLLIN) APPL_TRACE_DEBUG( " POLLIN "); \
61 if (events & POLLPRI) APPL_TRACE_DEBUG( " POLLPRI "); \
62 if (events & POLLOUT) APPL_TRACE_DEBUG( " POLLOUT "); \
63 if (events & POLLERR) APPL_TRACE_DEBUG( " POLLERR "); \
64 if (events & POLLHUP) APPL_TRACE_DEBUG( " POLLHUP "); \
65 if (events & POLLNVAL) APPL_TRACE_DEBUG(" POLLNVAL "); \
66 if (events & POLLRDHUP) APPL_TRACE_DEBUG(" POLLRDHUP"); \
The Android Open Source Project5738f832012-12-12 16:00:35 -080067 } while(0)
68
69#define MAX_THREAD 8
70#define MAX_POLL 64
71#define POLL_EXCEPTION_EVENTS (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL)
72#define IS_EXCEPTION(e) ((e) & POLL_EXCEPTION_EVENTS)
73#define IS_READ(e) ((e) & POLLIN)
74#define IS_WRITE(e) ((e) & POLLOUT)
75/*cmd executes in socket poll thread */
76#define CMD_WAKEUP 1
77#define CMD_EXIT 2
78#define CMD_ADD_FD 3
June R. Tate-Gansf8662042015-02-19 14:29:35 -080079#define CMD_REMOVE_FD 4
80#define CMD_USER_PRIVATE 5
The Android Open Source Project5738f832012-12-12 16:00:35 -080081
82typedef struct {
83 struct pollfd pfd;
84 uint32_t user_id;
85 int type;
86 int flags;
87} poll_slot_t;
88typedef struct {
89 int cmd_fdr, cmd_fdw;
90 int poll_count;
91 poll_slot_t ps[MAX_POLL];
92 int psi[MAX_POLL]; //index of poll slot
Ian Coolidgedf345992015-02-02 20:41:11 -080093 volatile pthread_t thread_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -080094 btsock_signaled_cb callback;
95 btsock_cmd_cb cmd_callback;
96 int used;
97} thread_slot_t;
98static thread_slot_t ts[MAX_THREAD];
99
The Android Open Source Project5738f832012-12-12 16:00:35 -0800100static void *sock_poll_thread(void *arg);
101static inline void close_cmd_fd(int h);
102
103static inline void add_poll(int h, int fd, int type, int flags, uint32_t user_id);
104
Ian Coolidge5381efc2015-02-02 20:39:09 -0800105static pthread_mutex_t thread_slot_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800106
Ian Coolidgedf345992015-02-02 20:41:11 -0800107static inline int create_thread(void *(*start_routine)(void *), void * arg,
108 pthread_t * thread_id)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800109{
110 pthread_attr_t thread_attr;
111 pthread_attr_init(&thread_attr);
112 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
Kim Schulz8372aa52015-03-25 10:39:40 +0100113 int policy;
114 int min_pri=0;
115 int ret = -1;
116 struct sched_param param;
Ian Coolidgeaba88ae2015-02-02 20:41:11 -0800117
Kim Schulz8372aa52015-03-25 10:39:40 +0100118 if ((ret = pthread_create(thread_id, &thread_attr, start_routine, arg))!=0 )
119 {
120 APPL_TRACE_ERROR("pthread_create : %s", strerror(errno));
121 return ret;
122 }
123 /* We need to lower the priority of this thread to ensure the stack gets
124 * priority over transfer to a socket */
125 pthread_getschedparam(*thread_id, &policy, &param);
126 min_pri = sched_get_priority_min(policy);
127 if (param.sched_priority > min_pri) {
128 param.sched_priority -= 1;
129 }
130 pthread_setschedparam(*thread_id, policy, &param);
131 return ret;
132}
The Android Open Source Project5738f832012-12-12 16:00:35 -0800133static void init_poll(int cmd_fd);
134static int alloc_thread_slot()
135{
136 int i;
137 //revserd order to save guard uninitialized access to 0 index
138 for(i = MAX_THREAD - 1; i >=0; i--)
139 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700140 APPL_TRACE_DEBUG("ts[%d].used:%d", i, ts[i].used);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800141 if(!ts[i].used)
142 {
143 ts[i].used = 1;
144 return i;
145 }
146 }
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700147 APPL_TRACE_ERROR("execeeded max thread count");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800148 return -1;
149}
150static void free_thread_slot(int h)
151{
152 if(0 <= h && h < MAX_THREAD)
153 {
154 close_cmd_fd(h);
155 ts[h].used = 0;
156 }
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700157 else APPL_TRACE_ERROR("invalid thread handle:%d", h);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800158}
159int btsock_thread_init()
160{
161 static int initialized;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700162 APPL_TRACE_DEBUG("in initialized:%d", initialized);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800163 if(!initialized)
164 {
165 initialized = 1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800166 int h;
167 for(h = 0; h < MAX_THREAD; h++)
168 {
169 ts[h].cmd_fdr = ts[h].cmd_fdw = -1;
170 ts[h].used = 0;
171 ts[h].thread_id = -1;
172 ts[h].poll_count = 0;
173 ts[h].callback = NULL;
174 ts[h].cmd_callback = NULL;
175 }
176 }
177 return TRUE;
178}
179int btsock_thread_create(btsock_signaled_cb callback, btsock_cmd_cb cmd_callback)
180{
The Android Open Source Project5738f832012-12-12 16:00:35 -0800181 asrt(callback || cmd_callback);
Ian Coolidge5381efc2015-02-02 20:39:09 -0800182 pthread_mutex_lock(&thread_slot_lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800183 int h = alloc_thread_slot();
Ian Coolidge5381efc2015-02-02 20:39:09 -0800184 pthread_mutex_unlock(&thread_slot_lock);
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700185 APPL_TRACE_DEBUG("alloc_thread_slot ret:%d", h);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800186 if(h >= 0)
187 {
188 init_poll(h);
Ian Coolidgedf345992015-02-02 20:41:11 -0800189 pthread_t thread;
190 int status = create_thread(sock_poll_thread, (void*)(uintptr_t)h, &thread);
191 if (status)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800192 {
Ian Coolidgedf345992015-02-02 20:41:11 -0800193 APPL_TRACE_ERROR("create_thread failed: %s", strerror(status));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800194 free_thread_slot(h);
Ian Coolidgedf345992015-02-02 20:41:11 -0800195 return -1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800196 }
Ian Coolidgedf345992015-02-02 20:41:11 -0800197
198 ts[h].thread_id = thread;
199 APPL_TRACE_DEBUG("h:%d, thread id:%d", h, ts[h].thread_id);
200 ts[h].callback = callback;
201 ts[h].cmd_callback = cmd_callback;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800202 }
203 return h;
204}
205
206/* create dummy socket pair used to wake up select loop */
207static inline void init_cmd_fd(int h)
208{
209 asrt(ts[h].cmd_fdr == -1 && ts[h].cmd_fdw == -1);
210 if(socketpair(AF_UNIX, SOCK_STREAM, 0, &ts[h].cmd_fdr) < 0)
211 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700212 APPL_TRACE_ERROR("socketpair failed: %s", strerror(errno));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800213 return;
214 }
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700215 APPL_TRACE_DEBUG("h:%d, cmd_fdr:%d, cmd_fdw:%d", h, ts[h].cmd_fdr, ts[h].cmd_fdw);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800216 //add the cmd fd for read & write
217 add_poll(h, ts[h].cmd_fdr, 0, SOCK_THREAD_FD_RD, 0);
218}
219static inline void close_cmd_fd(int h)
220{
221 if(ts[h].cmd_fdr != -1)
222 {
223 close(ts[h].cmd_fdr);
224 ts[h].cmd_fdr = -1;
225 }
226 if(ts[h].cmd_fdw != -1)
227 {
228 close(ts[h].cmd_fdw);
229 ts[h].cmd_fdw = -1;
230 }
231}
232typedef struct
233{
234 int id;
235 int fd;
236 int type;
237 int flags;
238 uint32_t user_id;
239} sock_cmd_t;
240int btsock_thread_add_fd(int h, int fd, int type, int flags, uint32_t user_id)
241{
242 if(h < 0 || h >= MAX_THREAD)
243 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700244 APPL_TRACE_ERROR("invalid bt thread handle:%d", h);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800245 return FALSE;
246 }
247 if(ts[h].cmd_fdw == -1)
248 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700249 APPL_TRACE_ERROR("cmd socket is not created. socket thread may not initialized");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800250 return FALSE;
251 }
252 if(flags & SOCK_THREAD_ADD_FD_SYNC)
253 {
254 //must executed in socket poll thread
255 if(ts[h].thread_id == pthread_self())
256 {
257 //cleanup one-time flags
258 flags &= ~SOCK_THREAD_ADD_FD_SYNC;
259 add_poll(h, fd, type, flags, user_id);
260 return TRUE;
261 }
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700262 APPL_TRACE_DEBUG("THREAD_ADD_FD_SYNC is not called in poll thread, fallback to async");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800263 }
264 sock_cmd_t cmd = {CMD_ADD_FD, fd, type, flags, user_id};
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700265 APPL_TRACE_DEBUG("adding fd:%d, flags:0x%x", fd, flags);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800266 return send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd);
267}
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800268
269bool btsock_thread_remove_fd_and_close(int thread_handle, int fd)
270{
271 if (thread_handle < 0 || thread_handle >= MAX_THREAD)
272 {
273 APPL_TRACE_ERROR("%s invalid thread handle: %d", __func__, thread_handle);
274 return false;
275 }
276 if (fd == -1)
277 {
278 APPL_TRACE_ERROR("%s invalid file descriptor.", __func__);
279 return false;
280 }
281
282 sock_cmd_t cmd = {CMD_REMOVE_FD, fd, 0, 0, 0};
283 return send(ts[thread_handle].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd);
284}
285
The Android Open Source Project5738f832012-12-12 16:00:35 -0800286int btsock_thread_post_cmd(int h, int type, const unsigned char* data, int size, uint32_t user_id)
287{
288 if(h < 0 || h >= MAX_THREAD)
289 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700290 APPL_TRACE_ERROR("invalid bt thread handle:%d", h);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800291 return FALSE;
292 }
293 if(ts[h].cmd_fdw == -1)
294 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700295 APPL_TRACE_ERROR("cmd socket is not created. socket thread may not initialized");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800296 return FALSE;
297 }
298 sock_cmd_t cmd = {CMD_USER_PRIVATE, 0, type, size, user_id};
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700299 APPL_TRACE_DEBUG("post cmd type:%d, size:%d, h:%d, ", type, size, h);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800300 sock_cmd_t* cmd_send = &cmd;
301 int size_send = sizeof(cmd);
302 if(data && size)
303 {
304 size_send = sizeof(cmd) + size;
305 cmd_send = (sock_cmd_t*)alloca(size_send);
306 if(cmd_send)
307 {
308 *cmd_send = cmd;
309 memcpy(cmd_send + 1, data, size);
310 }
311 else
312 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700313 APPL_TRACE_ERROR("alloca failed at h:%d, cmd type:%d, size:%d", h, type, size_send);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800314 return FALSE;
315 }
316 }
317 return send(ts[h].cmd_fdw, cmd_send, size_send, 0) == size_send;
318}
319int btsock_thread_wakeup(int h)
320{
321 if(h < 0 || h >= MAX_THREAD)
322 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700323 APPL_TRACE_ERROR("invalid bt thread handle:%d", h);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800324 return FALSE;
325 }
326 if(ts[h].cmd_fdw == -1)
327 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700328 APPL_TRACE_ERROR("thread handle:%d, cmd socket is not created", h);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800329 return FALSE;
330 }
331 sock_cmd_t cmd = {CMD_WAKEUP, 0, 0, 0, 0};
332 return send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd);
333}
334int btsock_thread_exit(int h)
335{
336 if(h < 0 || h >= MAX_THREAD)
337 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700338 APPL_TRACE_ERROR("invalid bt thread handle:%d", h);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800339 return FALSE;
340 }
341 if(ts[h].cmd_fdw == -1)
342 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700343 APPL_TRACE_ERROR("cmd socket is not created");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800344 return FALSE;
345 }
346 sock_cmd_t cmd = {CMD_EXIT, 0, 0, 0, 0};
347 if(send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd))
348 {
349 pthread_join(ts[h].thread_id, 0);
Ian Coolidge5381efc2015-02-02 20:39:09 -0800350 pthread_mutex_lock(&thread_slot_lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800351 free_thread_slot(h);
Ian Coolidge5381efc2015-02-02 20:39:09 -0800352 pthread_mutex_unlock(&thread_slot_lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800353 return TRUE;
354 }
355 return FALSE;
356}
357static void init_poll(int h)
358{
359 int i;
360 ts[h].poll_count = 0;
361 ts[h].thread_id = -1;
362 ts[h].callback = NULL;
363 ts[h].cmd_callback = NULL;
364 for(i = 0; i < MAX_POLL; i++)
365 {
366 ts[h].ps[i].pfd.fd = -1;
367 ts[h].psi[i] = -1;
368 }
369 init_cmd_fd(h);
370}
371static inline unsigned int flags2pevents(int flags)
372{
373 unsigned int pevents = 0;
374 if(flags & SOCK_THREAD_FD_WR)
375 pevents |= POLLOUT;
376 if(flags & SOCK_THREAD_FD_RD)
377 pevents |= POLLIN;
378 pevents |= POLL_EXCEPTION_EVENTS;
379 return pevents;
380}
381
382static inline void set_poll(poll_slot_t* ps, int fd, int type, int flags, uint32_t user_id)
383{
384 ps->pfd.fd = fd;
385 ps->user_id = user_id;
386 if(ps->type != 0 && ps->type != type)
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700387 APPL_TRACE_ERROR("poll socket type should not changed! type was:%d, type now:%d", ps->type, type);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800388 ps->type = type;
389 ps->flags = flags;
390 ps->pfd.events = flags2pevents(flags);
391 ps->pfd.revents = 0;
392}
393static inline void add_poll(int h, int fd, int type, int flags, uint32_t user_id)
394{
395 asrt(fd != -1);
396 int i;
397 int empty = -1;
398 poll_slot_t* ps = ts[h].ps;
399
400 for(i = 0; i < MAX_POLL; i++)
401 {
402 if(ps[i].pfd.fd == fd)
403 {
404 asrt(ts[h].poll_count < MAX_POLL);
405
406 set_poll(&ps[i], fd, type, flags | ps[i].flags, user_id);
407 return;
408 }
409 else if(empty < 0 && ps[i].pfd.fd == -1)
410 empty = i;
411 }
412 if(empty >= 0)
413 {
414 asrt(ts[h].poll_count < MAX_POLL);
415 set_poll(&ps[empty], fd, type, flags, user_id);
416 ++ts[h].poll_count;
417 return;
418 }
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700419 APPL_TRACE_ERROR("exceeded max poll slot:%d!", MAX_POLL);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800420}
421static inline void remove_poll(int h, poll_slot_t* ps, int flags)
422{
423 if(flags == ps->flags)
424 {
425 //all monitored events signaled. To remove it, just clear the slot
426 --ts[h].poll_count;
427 memset(ps, 0, sizeof(*ps));
428 ps->pfd.fd = -1;
429 }
430 else
431 {
432 //one read or one write monitor event signaled, removed the accordding bit
433 ps->flags &= ~flags;
434 //update the poll events mask
435 ps->pfd.events = flags2pevents(ps->flags);
436 }
437}
438static int process_cmd_sock(int h)
439{
440 sock_cmd_t cmd = {-1, 0, 0, 0, 0};
441 int fd = ts[h].cmd_fdr;
442 if(recv(fd, &cmd, sizeof(cmd), MSG_WAITALL) != sizeof(cmd))
443 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700444 APPL_TRACE_ERROR("recv cmd errno:%d", errno);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800445 return FALSE;
446 }
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700447 APPL_TRACE_DEBUG("cmd.id:%d", cmd.id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800448 switch(cmd.id)
449 {
450 case CMD_ADD_FD:
451 add_poll(h, cmd.fd, cmd.type, cmd.flags, cmd.user_id);
452 break;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800453 case CMD_REMOVE_FD:
454 for (int i = 1; i < MAX_POLL; ++i)
455 {
456 poll_slot_t *poll_slot = &ts[h].ps[i];
457 if (poll_slot->pfd.fd == cmd.fd)
458 {
459 remove_poll(h, poll_slot, poll_slot->flags);
460 break;
461 }
462 }
463 close(cmd.fd);
464 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800465 case CMD_WAKEUP:
466 break;
467 case CMD_USER_PRIVATE:
468 asrt(ts[h].cmd_callback);
469 if(ts[h].cmd_callback)
470 ts[h].cmd_callback(fd, cmd.type, cmd.flags, cmd.user_id);
471 break;
472 case CMD_EXIT:
473 return FALSE;
474 default:
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700475 APPL_TRACE_DEBUG("unknown cmd: %d", cmd.id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800476 break;
477 }
478 return TRUE;
479}
480static void process_data_sock(int h, struct pollfd *pfds, int count)
481{
482 asrt(count <= ts[h].poll_count);
483 int i;
484 for( i= 1; i < ts[h].poll_count; i++)
485 {
486 if(pfds[i].revents)
487 {
488 int ps_i = ts[h].psi[i];
489 asrt(pfds[i].fd == ts[h].ps[ps_i].pfd.fd);
490 uint32_t user_id = ts[h].ps[ps_i].user_id;
491 int type = ts[h].ps[ps_i].type;
492 int flags = 0;
493 print_events(pfds[i].revents);
494 if(IS_READ(pfds[i].revents))
495 {
496 flags |= SOCK_THREAD_FD_RD;
497 }
498 if(IS_WRITE(pfds[i].revents))
499 {
500 flags |= SOCK_THREAD_FD_WR;
501 }
502 if(IS_EXCEPTION(pfds[i].revents))
503 {
504 flags |= SOCK_THREAD_FD_EXCEPTION;
505 //remove the whole slot not flags
506 remove_poll(h, &ts[h].ps[ps_i], ts[h].ps[ps_i].flags);
507 }
508 else if(flags)
509 remove_poll(h, &ts[h].ps[ps_i], flags); //remove the monitor flags that already processed
510 if(flags)
511 ts[h].callback(pfds[i].fd, type, flags, user_id);
512 }
513 }
514}
515
516static void prepare_poll_fds(int h, struct pollfd* pfds)
517{
518 int count = 0;
519 int ps_i = 0;
520 int pfd_i = 0;
521 asrt(ts[h].poll_count <= MAX_POLL);
522 memset(pfds, 0, sizeof(pfds[0])*ts[h].poll_count);
523 while(count < ts[h].poll_count)
524 {
525 if(ps_i >= MAX_POLL)
526 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700527 APPL_TRACE_ERROR("exceed max poll range, ps_i:%d, MAX_POLL:%d, count:%d, ts[h].poll_count:%d",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800528 ps_i, MAX_POLL, count, ts[h].poll_count);
529 return;
530 }
531 if(ts[h].ps[ps_i].pfd.fd >= 0)
532 {
533 pfds[pfd_i] = ts[h].ps[ps_i].pfd;
534 ts[h].psi[pfd_i] = ps_i;
535 count++;
536 pfd_i++;
537 }
538 ps_i++;
539 }
540}
541static void *sock_poll_thread(void *arg)
542{
543 struct pollfd pfds[MAX_POLL];
544 memset(pfds, 0, sizeof(pfds));
Kévin PETIT22c6e502014-02-12 17:24:01 +0000545 int h = (intptr_t)arg;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800546 for(;;)
547 {
548 prepare_poll_fds(h, pfds);
549 int ret = poll(pfds, ts[h].poll_count, -1);
550 if(ret == -1)
551 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700552 APPL_TRACE_ERROR("poll ret -1, exit the thread, errno:%d, err:%s", errno, strerror(errno));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800553 break;
554 }
555 if(ret != 0)
556 {
557 int need_process_data_fd = TRUE;
558 if(pfds[0].revents) //cmd fd always is the first one
559 {
560 asrt(pfds[0].fd == ts[h].cmd_fdr);
561 if(!process_cmd_sock(h))
562 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700563 APPL_TRACE_DEBUG("h:%d, process_cmd_sock return false, exit...", h);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800564 break;
565 }
566 if(ret == 1)
567 need_process_data_fd = FALSE;
568 else ret--; //exclude the cmd fd
569 }
570 if(need_process_data_fd)
571 process_data_sock(h, pfds, ret);
572 }
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700573 else {APPL_TRACE_DEBUG("no data, select ret: %d", ret)};
The Android Open Source Project5738f832012-12-12 16:00:35 -0800574 }
575 ts[h].thread_id = -1;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700576 APPL_TRACE_DEBUG("socket poll thread exiting, h:%d", h);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800577 return 0;
578}