localtime/localtime_r lock issue

看了localtime/localtim_r的代码,里面确实有lock的操作,但有新发现。

在glibc的代码目录,time/localtime.c中,是localtime/localtime_r的实现:

struct tm _tmbuf;


/* Return the `struct tm' representation of *T in local time,
using *TP to store the result. */
struct tm *
__localtime_r (t, tp)
const time_t *t;
struct tm *tp;
{
return __tz_convert (t, 1, tp);
}
weak_alias (__localtime_r, localtime_r)


/* Return the `struct tm' representation of *T in local time. */
struct tm *
localtime (t)
const time_t *t;
{
return __tz_convert (t, 1, &_tmbuf);
}

从这几行代码看,是否reentrant,对比很明显。

接着再看time/tzset.c中__tz_convert函数的代码:

/* Return the `struct tm' representation of *TIMER in the local timezone.
Use local time if USE_LOCALTIME is nonzero, UTC otherwise. */
struct tm *
__tz_convert (const time_t *timer, int use_localtime, struct tm *tp)
{
long int leap_correction;
int leap_extra_secs;

if (timer == NULL)
{
__set_errno (EINVAL);
return NULL;
}

__libc_lock_lock (tzset_lock);

/* Update internal database according to current TZ setting.
POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname.
This is a good idea since this allows at least a bit more parallelism. */
tzset_internal (tp == &_tmbuf && use_localtime, 1);

if (__use_tzfile)
__tzfile_compute (*timer, use_localtime, &leap_correction,
&leap_extra_secs, tp);
else
{
if (! __offtime (timer, 0, tp))
tp = NULL;
else
__tz_compute (*timer, tp, use_localtime);
leap_correction = 0L;
leap_extra_secs = 0;
}

if (tp)
{
if (! use_localtime)
{
tp->tm_isdst = 0;
tp->tm_zone = "GMT";
tp->tm_gmtoff = 0L;
}

if (__offtime (timer, tp->tm_gmtoff - leap_correction, tp))
tp->tm_sec += leap_extra_secs;
else
tp = NULL;
}

__libc_lock_unlock (tzset_lock);

return tp;
}

其中进行了成对的加解锁操作,对tzset_lock这个变量。再看tzset_lock的声明和注释:

/* This locks all the state variables in tzfile.c and this file. */
__libc_lock_define_initialized (static, tzset_lock)

因为tzset_lock可以对两个文件中的变量都起作用,所以可以推出,需要tzset_lock保护的变量,肯定是或者包含于这两个文件的external变量中,同时,也可能包含这两个文件的文件局部变量(static)。

看一下,__tz_convert函数中,哪些操作需要锁住tzset_lock。__tz_convert函数中,从__libc_lock_lock (tzset_lock);语句之后看起。

首先,调用了tzset_internal函数,tzset_internal (tp == &_tmbuf && use_localtime, 1);,tzset_internal函数的实现如下:

/* Interpret the TZ envariable. */
static void
internal_function
tzset_internal (always, explicit)
int
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值