Android NDK互斥锁 [英] android NDK mutex locking

查看:206
本文介绍了Android NDK互斥锁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在将跨平台C ++引擎移植到Android,并注意到在调用 pthread_mutex_lock 时,它将莫名地(并且不一致)阻塞.该引擎已经在多个平台上使用了很多年,而有问题的代码已经多年没有改变了,所以我怀疑它是一个死锁或错误代码.它必须是我移植到Android的端口.

I've been porting a cross platform C++ engine to Android, and noticed that it will inexplicably (and inconsistently) block when calling pthread_mutex_lock. This engine has already been working for many years on several platforms, and the problematic code hasn't changed in years, so I doubt it's a deadlock or otherwise buggy code. It must be my port to Android..

到目前为止,代码中有几个地方会阻塞pthread_mutex_lock.它也不是完全可复制的.挂起时,LogCat中没有可疑的输出.

So far there are several places in the code that block on pthread_mutex_lock. It isn't entirely reproducible either. When it hangs, there's no suspicious output in LogCat.

我这样修改了互斥锁代码(为简便起见进行编辑...实际代码检查所有返回值):

I modified the mutex code like this (edited for brevity... real code checks all return values):

void MutexCreate( Mutex* m )
{
#ifdef WINDOWS
    InitializeCriticalSection( m );
#else ANDROID
    pthread_mutex_init( m, NULL );
#endif
}


void MutexDestroy( Mutex* m )
{
#ifdef WINDOWS
    DeleteCriticalSection( m );
#else ANDROID
    pthread_mutex_destroy( m, NULL );
#endif
}

void MutexLock( Mutex* m )
{
#ifdef WINDOWS
    EnterCriticalSection( m );
#else ANDROID
    pthread_mutex_lock( m );
#endif
}

void MutexUnlock( Mutex* m )
{
#ifdef WINDOWS
    LeaveCriticalSection( m );
#else ANDROID
    pthread_mutex_unlock( m );
#endif
}

我尝试修改MutexCreate来进行错误检查和递归互斥,但是没关系.我什至都没有收到错误或日志输出,所以这意味着我的互斥代码很好,或者没有显示错误/日志.操作系统如何准确通知您互斥量使用错误?

I tried modifying MutexCreate to make error-checking and recursive mutexes, but it didn't matter. I wasn't even getting errors or log output either, so either that means my mutex code is just fine, or the errors/logs weren't being shown. How exactly does the OS notify you of bad mutex usage?

引擎大量使用静态变量,包括互斥量.我看不到如何,但这是一个问题吗?我对此表示怀疑,因为我修改了许多要在堆上分配的互斥锁,并且发生了相同的行为.但这可能是因为我错过了一些静态互斥锁.我可能在这里抓稻草.

The engine makes heavy use of static variables, including mutexes. I can't see how, but is that a problem? I doubt it because I modified lots of mutexes to be allocated on the heap instead, and the same behavior occurred. But that may be because I missed some static mutexes. I'm probably grasping at straws here.

我阅读了一些参考资料,包括:

I read several references including:

http://pubs.opengroup.org/onlinepubs/7908799/xsh /pthread_mutex_init.html

http://www.embedded-linux.co.uk/tutorial/mutex_mutandis

http://linux.die.net/man/3/pthread_mutex_init

Android NDK Mutex

Android NDK问题pthread_mutex_unlock问题

推荐答案

错误检查"互斥对象将检查几件事(例如尝试递归使用非递归互斥对象),但没有什么特别之处.

The "errorcheck" mutexes will check a couple of things (like attempts to use a non-recursive mutex recursively) but nothing spectacular.

您说过真实代码检查所有返回值",因此如果任何pthread调用返回非零值,您的代码可能会爆炸. (不知道为什么您的pthread_mutex_destroy需要两个参数;假设存在复制和粘贴错误.)

You said "real code checks all return values", so presumably your code explodes if any pthread call returns a nonzero value. (Not sure why your pthread_mutex_destroy takes two args; assuming copy & paste error.)

pthread代码在Android中广泛使用,并且没有已知的挂断,因此在pthread实现本身中不太可能出现此问题.

The pthread code is widely used within Android and has no known hangups, so the issue is not likely in the pthread implementation itself.

当前互斥锁的实现适合32位,因此,如果将*(pthread_mutex_t* mut)打印为整数,则应该能够弄清楚其处于什么状态(从技术上讲,处于什么状态)过去的某个时刻). bionic/libc/bionic/pthread.c中的定义是:

The current implementation of mutexes fits in 32 bits, so if you print *(pthread_mutex_t* mut) as an integer you should be able to figure out what state it's in (technically, what state it was in at some point in the past). The definition in bionic/libc/bionic/pthread.c is:

/* a mutex is implemented as a 32-bit integer holding the following fields
 *
 * bits:     name     description
 * 31-16     tid      owner thread's kernel id (recursive and errorcheck only)
 * 15-14     type     mutex type
 * 13        shared   process-shared flag
 * 12-2      counter  counter of recursive mutexes
 * 1-0       state    lock state (0, 1 or 2)
 */

快速"互斥锁的类型为0,并且不设置tid字段.实际上,通用互斥锁的值为0(不保留),1(保留)或2(保留,有争用).如果您看到一个快速互斥量的值是 not 其中之一,则可能是出现并踩踏了它.

"Fast" mutexes have a type of 0, and don't set the tid field. In fact, a generic mutex will have a value of 0 (not held), 1 (held), or 2 (held, with contention). If you ever see a fast mutex whose value is not one of those, chances are something came along and stomped on it.

这也意味着,如果将程序配置为使用递归互斥锁,则可以通过拉出位来查看哪个线程持有该互斥锁(在trylock指示您将要停止时打印互斥锁值,或者转储)在挂起的进程上使用gdb状态).加上ps -t的输出,您将知道锁定互斥锁的线程是否仍然存在.

It also means that, if you configure your program to use recursive mutexes, you can see which thread holds the mutex by pulling the bits out (either by printing the mutex value when trylock indicates you're about to stall, or dumping state with gdb on a hung process). That, plus the output of ps -t, will let you know if the thread that locked the mutex still exists.

这篇关于Android NDK互斥锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆