Split time functions into rs_time.rsh header.
Change-Id: I598b0031d15749c91d11fbd37b075d0564a94dbf
diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
index a50321e..fc3a065 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
+++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
@@ -66,6 +66,7 @@
unitTests.add(new UT_primitives(this, mRes, mCtx));
unitTests.add(new UT_rsdebug(this, mRes, mCtx));
+ unitTests.add(new UT_rstime(this, mRes, mCtx));
unitTests.add(new UT_rstypes(this, mRes, mCtx));
unitTests.add(new UT_fp_mad(this, mRes, mCtx));
/*
diff --git a/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java b/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java
new file mode 100644
index 0000000..f302e1a
--- /dev/null
+++ b/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_rstime extends UnitTest {
+ private Resources mRes;
+
+ protected UT_rstime(RSTestCore rstc, Resources res, Context ctx) {
+ super(rstc, "rsTime", ctx);
+ mRes = res;
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create(mCtx);
+ ScriptC_rstime s = new ScriptC_rstime(pRS, mRes, R.raw.rstime);
+ pRS.setMessageHandler(mRsMessage);
+ s.invoke_test_rstime(0, 0);
+ pRS.finish();
+ waitForMessage();
+ pRS.destroy();
+ }
+}
diff --git a/libs/rs/java/tests/src/com/android/rs/test/rstime.rs b/libs/rs/java/tests/src/com/android/rs/test/rstime.rs
new file mode 100644
index 0000000..5e3e078
--- /dev/null
+++ b/libs/rs/java/tests/src/com/android/rs/test/rstime.rs
@@ -0,0 +1,52 @@
+#include "shared.rsh"
+
+static bool basic_test(uint32_t index) {
+ bool failed = false;
+
+ rs_time_t curTime = rsTime(0);
+ rs_tm tm;
+ rsDebug("curTime", curTime);
+
+ rsLocaltime(&tm, &curTime);
+
+ rsDebug("tm.tm_sec", tm.tm_sec);
+ rsDebug("tm.tm_min", tm.tm_min);
+ rsDebug("tm.tm_hour", tm.tm_hour);
+ rsDebug("tm.tm_mday", tm.tm_mday);
+ rsDebug("tm.tm_mon", tm.tm_mon);
+ rsDebug("tm.tm_year", tm.tm_year);
+ rsDebug("tm.tm_wday", tm.tm_wday);
+ rsDebug("tm.tm_yday", tm.tm_yday);
+ rsDebug("tm.tm_isdst", tm.tm_isdst);
+
+ // Test a specific time (only valid for PST localtime)
+ curTime = 1294438893;
+ rsLocaltime(&tm, &curTime);
+
+ _RS_ASSERT(tm.tm_sec == 33);
+ _RS_ASSERT(tm.tm_min == 21);
+ _RS_ASSERT(tm.tm_hour == 14);
+ _RS_ASSERT(tm.tm_mday == 7);
+ _RS_ASSERT(tm.tm_mon == 0);
+ _RS_ASSERT(tm.tm_year == 111);
+ _RS_ASSERT(tm.tm_wday == 5);
+ _RS_ASSERT(tm.tm_yday == 6);
+ _RS_ASSERT(tm.tm_isdst == 0);
+
+ return failed;
+}
+
+void test_rstime(uint32_t index, int test_num) {
+ bool failed = false;
+ failed |= basic_test(index);
+
+ if (failed) {
+ rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+ rsDebug("rstime_test FAILED", -1);
+ }
+ else {
+ rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+ rsDebug("rstime_test PASSED", 0);
+ }
+}
+
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 6a065b2..c5ee7ee 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -44,6 +44,7 @@
uint32_t Context::gThreadTLSKeyCount = 0;
uint32_t Context::gGLContextCount = 0;
pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t Context::gLibMutex = PTHREAD_MUTEX_INITIALIZER;
static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
if (returnVal != EGL_TRUE) {
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 3c402c4..df275bc 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -75,6 +75,8 @@
static uint32_t gThreadTLSKeyCount;
static uint32_t gGLContextCount;
static pthread_mutex_t gInitMutex;
+ // Library mutex (for providing thread-safe calls from the runtime)
+ static pthread_mutex_t gLibMutex;
struct ScriptTLSStruct {
Context * mContext;
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index f61b983..0b21669 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -100,70 +100,24 @@
// Time routines
//////////////////////////////////////////////////////////////////////////////
-static int32_t SC_second() {
+static time_t SC_time(time_t *timer) {
GET_TLS();
-
- time_t rawtime;
- time(&rawtime);
-
- struct tm *timeinfo;
- timeinfo = localtime(&rawtime);
- return timeinfo->tm_sec;
+ return time(timer);
}
-static int32_t SC_minute() {
+static tm* SC_localtime(tm *local, time_t *timer) {
GET_TLS();
+ if (!local) {
+ return NULL;
+ }
- time_t rawtime;
- time(&rawtime);
-
- struct tm *timeinfo;
- timeinfo = localtime(&rawtime);
- return timeinfo->tm_min;
-}
-
-static int32_t SC_hour() {
- GET_TLS();
-
- time_t rawtime;
- time(&rawtime);
-
- struct tm *timeinfo;
- timeinfo = localtime(&rawtime);
- return timeinfo->tm_hour;
-}
-
-static int32_t SC_day() {
- GET_TLS();
-
- time_t rawtime;
- time(&rawtime);
-
- struct tm *timeinfo;
- timeinfo = localtime(&rawtime);
- return timeinfo->tm_mday;
-}
-
-static int32_t SC_month() {
- GET_TLS();
-
- time_t rawtime;
- time(&rawtime);
-
- struct tm *timeinfo;
- timeinfo = localtime(&rawtime);
- return timeinfo->tm_mon;
-}
-
-static int32_t SC_year() {
- GET_TLS();
-
- time_t rawtime;
- time(&rawtime);
-
- struct tm *timeinfo;
- timeinfo = localtime(&rawtime);
- return timeinfo->tm_year;
+ // The native localtime function is not thread-safe, so we
+ // have to apply locking for proper behavior in RenderScript.
+ pthread_mutex_lock(&rsc->gLibMutex);
+ tm *tmp = localtime(timer);
+ memcpy(local, tmp, sizeof(*tmp));
+ pthread_mutex_unlock(&rsc->gLibMutex);
+ return local;
}
static int64_t SC_uptimeMillis() {
@@ -498,12 +452,8 @@
{ "_Z6rsFracf", (void *)&SC_frac, true },
// time
- { "_Z8rsSecondv", (void *)&SC_second, true },
- { "_Z8rsMinutev", (void *)&SC_minute, true },
- { "_Z6rsHourv", (void *)&SC_hour, true },
- { "_Z5rsDayv", (void *)&SC_day, true },
- { "_Z7rsMonthv", (void *)&SC_month, true },
- { "_Z6rsYearv", (void *)&SC_year, true },
+ { "_Z6rsTimePi", (void *)&SC_time, true },
+ { "_Z11rsLocaltimeP5rs_tmPKi", (void *)&SC_localtime, true },
{ "_Z14rsUptimeMillisv", (void*)&SC_uptimeMillis, true },
{ "_Z13rsUptimeNanosv", (void*)&SC_uptimeNanos, true },
{ "_Z7rsGetDtv", (void*)&SC_getDt, false },
diff --git a/libs/rs/scriptc/rs_math.rsh b/libs/rs/scriptc/rs_math.rsh
index d059997..a74c0e0 100644
--- a/libs/rs/scriptc/rs_math.rsh
+++ b/libs/rs/scriptc/rs_math.rsh
@@ -118,32 +118,6 @@
extern float __attribute__((overloadable))
rsFrac(float);
-// time
-extern int32_t __attribute__((overloadable))
- rsSecond(void);
-extern int32_t __attribute__((overloadable))
- rsMinute(void);
-extern int32_t __attribute__((overloadable))
- rsHour(void);
-extern int32_t __attribute__((overloadable))
- rsDay(void);
-extern int32_t __attribute__((overloadable))
- rsMonth(void);
-extern int32_t __attribute__((overloadable))
- rsYear(void);
-
-// Return the current system clock in milliseconds
-extern int64_t __attribute__((overloadable))
- rsUptimeMillis(void);
-
-// Return the current system clock in nanoseconds
-extern int64_t __attribute__((overloadable))
- rsUptimeNanos(void);
-
-// Return the time in seconds since function was last called in this script.
-extern float __attribute__((overloadable))
- rsGetDt(void);
-
// Send a message back to the client. Will not block and returns true
// if the message was sendable and false if the fifo was full.
// A message ID is required. Data payload is optional.
diff --git a/libs/rs/scriptc/rs_time.rsh b/libs/rs/scriptc/rs_time.rsh
new file mode 100644
index 0000000..f1abed63
--- /dev/null
+++ b/libs/rs/scriptc/rs_time.rsh
@@ -0,0 +1,36 @@
+#ifndef __RS_TIME_RSH__
+#define __RS_TIME_RSH__
+
+typedef int rs_time_t;
+
+typedef struct {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+} rs_tm;
+
+extern rs_time_t __attribute__((overloadable))
+ rsTime(rs_time_t *timer);
+
+extern rs_tm * __attribute__((overloadable))
+ rsLocaltime(rs_tm *local, const rs_time_t *timer);
+
+// Return the current system clock in milliseconds
+extern int64_t __attribute__((overloadable))
+ rsUptimeMillis(void);
+
+// Return the current system clock in nanoseconds
+extern int64_t __attribute__((overloadable))
+ rsUptimeNanos(void);
+
+// Return the time in seconds since function was last called in this script.
+extern float __attribute__((overloadable))
+ rsGetDt(void);
+
+#endif