|
40 | 40 | #include <vector> |
41 | 41 | #include <unistd.h> |
42 | 42 |
|
43 | | -static SpinLock _rec_lock(0); |
44 | | - |
45 | 43 | static const char *const SETTING_RING[] = {NULL, "kernel", "user", "any"}; |
46 | 44 | static const char *const SETTING_CSTACK[] = {NULL, "no", "fp", "dwarf", "lbr"}; |
47 | 45 |
|
@@ -1484,159 +1482,177 @@ Error FlightRecorder::newRecording(bool reset) { |
1484 | 1482 | return Error("Could not open Flight Recorder output file"); |
1485 | 1483 | } |
1486 | 1484 |
|
1487 | | - // Given some of reads are not protected by _rec_lock, |
1488 | | - // we want to publish _rec with full fence, so that read |
1489 | | - // side cannot see partially initialized recording. |
1490 | | - Recording* tmp = new Recording(fd, _args); |
1491 | | - __atomic_store_n(&_rec, tmp, __ATOMIC_SEQ_CST); |
| 1485 | + _rec = new Recording(fd, _args); |
1492 | 1486 | return Error::OK; |
1493 | 1487 | } |
1494 | 1488 |
|
1495 | 1489 | void FlightRecorder::stop() { |
1496 | 1490 | ExclusiveLockGuard locker(&_rec_lock); |
1497 | | - if (_rec != NULL) { |
1498 | | - volatile Recording *tmp = _rec; |
| 1491 | + Recording* rec = _rec; |
| 1492 | + if (rec != nullptr) { |
1499 | 1493 | // NULL first, deallocate later |
1500 | | - __atomic_store_n(&_rec, nullptr, __ATOMIC_RELAXED); |
1501 | | - delete tmp; |
| 1494 | + _rec = nullptr; |
| 1495 | + delete rec; |
1502 | 1496 | } |
1503 | 1497 | } |
1504 | 1498 |
|
1505 | 1499 | Error FlightRecorder::dump(const char *filename, const int length) { |
1506 | 1500 | ExclusiveLockGuard locker(&_rec_lock); |
1507 | | - if (_rec != NULL) { |
| 1501 | + Recording* rec = _rec; |
| 1502 | + if (rec != nullptr) { |
1508 | 1503 | if (_filename.length() != length || |
1509 | 1504 | strncmp(filename, _filename.c_str(), length) != 0) { |
1510 | 1505 | // if the filename to dump the recording to is specified move the current |
1511 | 1506 | // working file there |
1512 | 1507 | int copy_fd = open(filename, O_CREAT | O_RDWR | O_TRUNC, 0644); |
1513 | | - _rec->switchChunk(copy_fd); |
| 1508 | + rec->switchChunk(copy_fd); |
1514 | 1509 | close(copy_fd); |
1515 | | - } else { |
1516 | | - return Error( |
1517 | | - "Can not dump recording to itself. Provide a different file name!"); |
| 1510 | + return Error::OK; |
1518 | 1511 | } |
1519 | | - |
1520 | | - return Error::OK; |
1521 | | - } else { |
1522 | | - return Error("No active recording"); |
| 1512 | + return Error( |
| 1513 | + "Can not dump recording to itself. Provide a different file name!"); |
1523 | 1514 | } |
| 1515 | + return Error("No active recording"); |
1524 | 1516 | } |
1525 | 1517 |
|
1526 | 1518 | void FlightRecorder::flush() { |
1527 | 1519 | ExclusiveLockGuard locker(&_rec_lock); |
1528 | | - if (_rec != NULL) { |
1529 | | - jvmtiEnv *jvmti = VM::jvmti(); |
1530 | | - JNIEnv *env = VM::jni(); |
| 1520 | + Recording* rec = _rec; |
| 1521 | + if (rec != nullptr) { |
| 1522 | + jvmtiEnv* jvmti = VM::jvmti(); |
| 1523 | + JNIEnv* env = VM::jni(); |
1531 | 1524 |
|
1532 | | - jclass **classes = NULL; |
| 1525 | + jclass** classes = NULL; |
1533 | 1526 | jint count = 0; |
1534 | 1527 | // obtaining the class list will create local refs to all loaded classes, |
1535 | 1528 | // effectively preventing them from being unloaded while flushing |
1536 | 1529 | jvmtiError err = jvmti->GetLoadedClasses(&count, classes); |
1537 | | - _rec->switchChunk(-1); |
| 1530 | + rec->switchChunk(-1); |
1538 | 1531 | if (!err) { |
1539 | 1532 | // deallocate all loaded classes |
1540 | 1533 | for (int i = 0; i < count; i++) { |
1541 | | - env->DeleteLocalRef((jobject)classes[i]); |
1542 | | - jvmti->Deallocate((unsigned char *)classes[i]); |
| 1534 | + env->DeleteLocalRef((jobject) classes[i]); |
| 1535 | + jvmti->Deallocate((unsigned char*) classes[i]); |
1543 | 1536 | } |
1544 | 1537 | } |
1545 | 1538 | } |
1546 | 1539 | } |
1547 | 1540 |
|
1548 | 1541 | void FlightRecorder::wallClockEpoch(int lock_index, |
1549 | 1542 | WallClockEpochEvent *event) { |
1550 | | - if (_rec != NULL) { |
1551 | | - Buffer *buf = _rec->buffer(lock_index); |
1552 | | - _rec->recordWallClockEpoch(buf, event); |
| 1543 | + OptionalSharedLockGuard locker(&_rec_lock); |
| 1544 | + if (locker.ownsLock()) { |
| 1545 | + Recording* rec = _rec; |
| 1546 | + if (rec != nullptr) { |
| 1547 | + Buffer *buf = rec->buffer(lock_index); |
| 1548 | + rec->recordWallClockEpoch(buf, event); |
| 1549 | + } |
1553 | 1550 | } |
1554 | 1551 | } |
1555 | 1552 |
|
1556 | 1553 | void FlightRecorder::recordTraceRoot(int lock_index, int tid, |
1557 | 1554 | TraceRootEvent *event) { |
1558 | | - if (_rec != NULL) { |
1559 | | - Buffer *buf = _rec->buffer(lock_index); |
1560 | | - _rec->recordTraceRoot(buf, tid, event); |
| 1555 | + OptionalSharedLockGuard locker(&_rec_lock); |
| 1556 | + if (locker.ownsLock()) { |
| 1557 | + Recording* rec = _rec; |
| 1558 | + if (rec != nullptr) { |
| 1559 | + Buffer *buf = rec->buffer(lock_index); |
| 1560 | + rec->recordTraceRoot(buf, tid, event); |
| 1561 | + } |
1561 | 1562 | } |
1562 | 1563 | } |
1563 | 1564 |
|
1564 | 1565 | void FlightRecorder::recordQueueTime(int lock_index, int tid, |
1565 | 1566 | QueueTimeEvent *event) { |
1566 | | - if (_rec != NULL) { |
1567 | | - Buffer *buf = _rec->buffer(lock_index); |
1568 | | - _rec->recordQueueTime(buf, tid, event); |
| 1567 | + OptionalSharedLockGuard locker(&_rec_lock); |
| 1568 | + if (locker.ownsLock()) { |
| 1569 | + Recording* rec = _rec; |
| 1570 | + if (rec != nullptr) { |
| 1571 | + Buffer *buf = rec->buffer(lock_index); |
| 1572 | + rec->recordQueueTime(buf, tid, event); |
| 1573 | + } |
1569 | 1574 | } |
1570 | 1575 | } |
1571 | 1576 |
|
1572 | 1577 | void FlightRecorder::recordDatadogSetting(int lock_index, int length, |
1573 | 1578 | const char *name, const char *value, |
1574 | 1579 | const char *unit) { |
1575 | | - if (_rec != NULL) { |
1576 | | - Buffer *buf = _rec->buffer(lock_index); |
1577 | | - _rec->writeDatadogSetting(buf, length, name, value, unit); |
| 1580 | + OptionalSharedLockGuard locker(&_rec_lock); |
| 1581 | + if (locker.ownsLock()) { |
| 1582 | + Recording* rec = _rec; |
| 1583 | + if (rec != nullptr) { |
| 1584 | + Buffer *buf = rec->buffer(lock_index); |
| 1585 | + rec->writeDatadogSetting(buf, length, name, value, unit); |
| 1586 | + } |
1578 | 1587 | } |
1579 | 1588 | } |
1580 | 1589 |
|
1581 | 1590 | void FlightRecorder::recordHeapUsage(int lock_index, long value, bool live) { |
1582 | | - if (_rec != NULL) { |
1583 | | - Buffer *buf = _rec->buffer(lock_index); |
1584 | | - _rec->writeHeapUsage(buf, value, live); |
| 1591 | + OptionalSharedLockGuard locker(&_rec_lock); |
| 1592 | + if (locker.ownsLock()) { |
| 1593 | + Recording* rec = _rec; |
| 1594 | + if (rec != nullptr) { |
| 1595 | + Buffer *buf = rec->buffer(lock_index); |
| 1596 | + rec->writeHeapUsage(buf, value, live); |
| 1597 | + } |
1585 | 1598 | } |
1586 | 1599 | } |
1587 | 1600 |
|
1588 | 1601 | void FlightRecorder::recordEvent(int lock_index, int tid, u64 call_trace_id, |
1589 | 1602 | int event_type, Event *event) { |
1590 | | - if (_rec != NULL) { |
1591 | | - RecordingBuffer *buf = _rec->buffer(lock_index); |
1592 | | - switch (event_type) { |
1593 | | - case 0: |
1594 | | - _rec->recordExecutionSample(buf, tid, call_trace_id, |
| 1603 | + OptionalSharedLockGuard locker(&_rec_lock); |
| 1604 | + if (locker.ownsLock()) { |
| 1605 | + Recording* rec = _rec; |
| 1606 | + if (rec != nullptr) { |
| 1607 | + RecordingBuffer *buf = rec->buffer(lock_index); |
| 1608 | + switch (event_type) { |
| 1609 | + case 0: |
| 1610 | + rec->recordExecutionSample(buf, tid, call_trace_id, |
| 1611 | + (ExecutionEvent *)event); |
| 1612 | + break; |
| 1613 | + case BCI_WALL: |
| 1614 | + rec->recordMethodSample(buf, tid, call_trace_id, |
1595 | 1615 | (ExecutionEvent *)event); |
1596 | | - break; |
1597 | | - case BCI_WALL: |
1598 | | - _rec->recordMethodSample(buf, tid, call_trace_id, |
1599 | | - (ExecutionEvent *)event); |
1600 | | - break; |
1601 | | - case BCI_ALLOC: |
1602 | | - _rec->recordAllocation(buf, tid, call_trace_id, (AllocEvent *)event); |
1603 | | - break; |
1604 | | - case BCI_LIVENESS: |
1605 | | - _rec->recordHeapLiveObject(buf, tid, call_trace_id, |
1606 | | - (ObjectLivenessEvent *)event); |
1607 | | - break; |
1608 | | - case BCI_LOCK: |
1609 | | - _rec->recordMonitorBlocked(buf, tid, call_trace_id, (LockEvent *)event); |
1610 | | - break; |
1611 | | - case BCI_PARK: |
1612 | | - _rec->recordThreadPark(buf, tid, call_trace_id, (LockEvent *)event); |
1613 | | - break; |
1614 | | - } |
1615 | | - _rec->flushIfNeeded(buf); |
1616 | | - _rec->addThread(lock_index, tid); |
| 1616 | + break; |
| 1617 | + case BCI_ALLOC: |
| 1618 | + rec->recordAllocation(buf, tid, call_trace_id, (AllocEvent *)event); |
| 1619 | + break; |
| 1620 | + case BCI_LIVENESS: |
| 1621 | + rec->recordHeapLiveObject(buf, tid, call_trace_id, |
| 1622 | + (ObjectLivenessEvent *)event); |
| 1623 | + break; |
| 1624 | + case BCI_LOCK: |
| 1625 | + rec->recordMonitorBlocked(buf, tid, call_trace_id, (LockEvent *)event); |
| 1626 | + break; |
| 1627 | + case BCI_PARK: |
| 1628 | + rec->recordThreadPark(buf, tid, call_trace_id, (LockEvent *)event); |
| 1629 | + break; |
| 1630 | + } |
| 1631 | + rec->flushIfNeeded(buf); |
| 1632 | + rec->addThread(lock_index, tid); |
| 1633 | + } |
1617 | 1634 | } |
1618 | 1635 | } |
1619 | 1636 |
|
1620 | 1637 | void FlightRecorder::recordLog(LogLevel level, const char *message, |
1621 | 1638 | size_t len) { |
1622 | | - if (!_rec_lock.tryLockShared()) { |
1623 | | - // No active recording |
1624 | | - return; |
1625 | | - } |
1626 | | - |
1627 | | - if (len > MAX_STRING_LENGTH) |
1628 | | - len = MAX_STRING_LENGTH; |
1629 | | - // cppcheck-suppress obsoleteFunctions |
1630 | | - Buffer *buf = (Buffer *)alloca(len + 40); |
1631 | | - buf->reset(); |
| 1639 | + OptionalSharedLockGuard locker(&_rec_lock); |
| 1640 | + if (locker.ownsLock()) { |
| 1641 | + Recording* rec = _rec; |
| 1642 | + if (rec != nullptr) { |
| 1643 | + if (len > MAX_STRING_LENGTH) |
| 1644 | + len = MAX_STRING_LENGTH; |
| 1645 | + // cppcheck-suppress obsoleteFunctions |
| 1646 | + Buffer *buf = (Buffer *)alloca(len + 40); |
| 1647 | + buf->reset(); |
1632 | 1648 |
|
1633 | | - int start = buf->skip(5); |
1634 | | - buf->putVar64(T_LOG); |
1635 | | - buf->putVar64(TSC::ticks()); |
1636 | | - buf->putVar64(level); |
1637 | | - buf->putUtf8(message, len); |
1638 | | - buf->putVar32(start, buf->offset() - start); |
1639 | | - _rec->flush(buf); |
1640 | | - |
1641 | | - _rec_lock.unlockShared(); |
| 1649 | + int start = buf->skip(5); |
| 1650 | + buf->putVar64(T_LOG); |
| 1651 | + buf->putVar64(TSC::ticks()); |
| 1652 | + buf->putVar64(level); |
| 1653 | + buf->putUtf8(message, len); |
| 1654 | + buf->putVar32(start, buf->offset() - start); |
| 1655 | + _rec->flush(buf); |
| 1656 | + } |
| 1657 | + } |
1642 | 1658 | } |
0 commit comments