-
Notifications
You must be signed in to change notification settings - Fork 12.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc] implement localtime #110363
base: main
Are you sure you want to change the base?
[libc] implement localtime #110363
Conversation
✅ With the latest revision this PR passed the C/C++ code formatter. |
6e15b2f
to
15a5bef
Compare
95ad2ec
to
4e12c67
Compare
469939e
to
47a3589
Compare
Instead of using |
libc/src/time/time_utils.cpp
Outdated
char timezone[TimeConstants::TIMEZONE_SIZE]; | ||
char *env_tz = getenv("TZ"); | ||
FILE *fp = NULL; | ||
if (env_tz) { | ||
strncpy(timezone, env_tz, sizeof(timezone)); | ||
timezone[sizeof(timezone) - 1] = '\0'; | ||
} else { | ||
fp = fopen("/etc/timezone", "rb"); | ||
if (fp == NULL) { | ||
return time_utils::out_of_range(); | ||
} | ||
|
||
acquire_file(fp, timezone, TimeConstants::TIMEZONE_SIZE); | ||
} | ||
|
||
if (fp != NULL && file_usage == 0) { | ||
release_file(fp, timezone); | ||
return time_utils::out_of_range(); | ||
} | ||
|
||
int offset = timezone::get_timezone_offset(timezone); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic should be moved into an internal utlity function that could be implemented differently for each platform. For example, on baremetal we don't have any filesystem and fopen
isn't defined at all. Ideally, this function should return a struct type rather than a string so on platforms like baremetal we can return statically initialized global and avoid having to parse the string on every call (even in the Linux implementation you probably want to memoize it for performance reasons).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I am currently refactoring the logic by parsing /etc/localtime
by using the TZif
file format.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am now using open
instead of fopen
to be compatible on other platforms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not about open
vs fopen
, on platforms like baremetal there's no filesystem at all, so any use file descriptors or I/O operations like read
is a non-starter. This needs to be refactored so the common logic can be used across all platforms, and the filesystem bits should live in platforms specific implementation (e.g. src/time/linux
). On platforms where filesystem is available, we should be using the internal API like LIBC_NAMESPACE::openfile
rather than the POSIX API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I will refactor I/O operations. I think the best way would be to implement an "interface" such that all platforms could use. Where filesystem is available, I will use LIBC_NAMESPACE::openfile
and use the "interface". Is this a good approach? Thank you for the help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After investigating this, I think I understand the architecture. I will move all Linux to /src/time/linux
and will implement a more platform independent approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have now refactored to use the internal API openfile
and localtime implementations are in src/time/linux
directory. The timezone.cpp/timezone.h
files are not in the linux
directory. Should these also be there?
libc/src/time/time_utils.cpp
Outdated
volatile int file_usage = 0; | ||
|
||
void release_file(FILE *fp, char *timezone) { | ||
file_usage = 0; | ||
fclose(fp); | ||
} | ||
|
||
void acquire_file(FILE *fp, char *timezone, size_t timezone_size) { | ||
while (1) { | ||
if (file_usage == 0) { | ||
file_usage = 1; | ||
break; | ||
} | ||
} | ||
|
||
if (fgets(timezone, (int)timezone_size, fp) == NULL) { | ||
release_file(fp, timezone); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file related logic should ideally be wrapped in an RAII type to make sure the file is always closed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I have now implemented an RAII correctly. Could you please check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any RAII use, have you pushed all your changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have an implementation in time_utils.cpp
lines 30-46, where it is possible to get the file and release the file. Please do let me know if I have misunderstood RAII, so I can update this implementation.
5c51ae3
to
316e0a9
Compare
Even though this pull request is not yet finished, I thought it would be great to get a review since this pull request is getting quite big. There are some unit tests that are not working, and have been commented out. |
eca1d44
to
1456c67
Compare
dada1e2
to
ea3d0b9
Compare
This is an implementation of localtime. Closes llvm#107597 and llvm#109892
format code with clang-format
fix: dst
fix: dst
update test for `localtime_r`
remove unnecessary code
fix: dst
compatibility reasons
2f14147
to
6a84f62
Compare
Consider marking this as a "draft" in the github UI. |
This is a large change and there are some aspects that will likely require more discussion, like what kind of TZ support we even want and how to do it, whether we could share the implementation with libc++, etc. This could be discussed either on Discourse or at the public LLVM-libc meeting (or both). In the meantime, I think the best path forward would be to split this change into multiple changes, with the first one being just an empty minimal implementation which could be merged while we're discussing the implementation details. |
This is an implementation of localtime (currently not finished).
Closes #107597 and #109892