• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "mem/gc/gc_queue.h"
17 
18 #include "include/runtime.h"
19 #include "libpandabase/utils/time.h"
20 #include "runtime/mem/gc/gc.h"
21 
22 namespace panda::mem {
23 
24 const int64_t NANOSECONDS_PER_MILLISEC = 1000000;
25 
GetTask()26 GCTask *GCQueueWithTime::GetTask()
27 {
28     os::memory::LockHolder lock(lock_);
29     while (queue_.empty()) {
30         if (!gc_->IsGCRunning()) {
31             LOG(DEBUG, GC) << "GetTask() Return INVALID_CAUSE";
32             return nullptr;
33         }
34         LOG(DEBUG, GC) << "Empty " << queue_name_ << ", waiting...";
35         cond_var_.Wait(&lock_);
36     }
37     GCTask *task = queue_.top();
38     auto current_time = time::GetCurrentTimeInNanos();
39     while (gc_->IsGCRunning() && (task->GetTargetTime() >= current_time)) {
40         auto delta = task->GetTargetTime() - current_time;
41         uint64_t ms = delta / NANOSECONDS_PER_MILLISEC;
42         uint64_t ns = delta % NANOSECONDS_PER_MILLISEC;
43         LOG(DEBUG, GC) << "GetTask TimedWait";
44         cond_var_.TimedWait(&lock_, ms, ns);
45         task = queue_.top();
46         current_time = time::GetCurrentTimeInNanos();
47     }
48     queue_.pop();
49     LOG(DEBUG, GC) << "Extract a task from a " << queue_name_;
50     return task;
51 }
52 
AddTask(GCTask * task)53 void GCQueueWithTime::AddTask(GCTask *task)
54 {
55     os::memory::LockHolder lock(lock_);
56     if (finalized) {
57         LOG(DEBUG, GC) << "Skip AddTask to queue: " << queue_name_ << " cause it's finalized already";
58         task->Release(gc_->GetInternalAllocator());
59         return;
60     }
61     LOG(DEBUG, GC) << "Add task to a " << queue_name_;
62     if (!queue_.empty()) {
63         auto last_elem = queue_.top();
64         if (last_elem->reason_ == task->reason_) {
65             // do not duplicate GC task with the same reason.
66             task->Release(gc_->GetInternalAllocator());
67             return;
68         }
69     }
70     queue_.push(task);
71     cond_var_.Signal();
72 }
73 
Finalize()74 void GCQueueWithTime::Finalize()
75 {
76     os::memory::LockHolder lock(lock_);
77     finalized = true;
78     LOG(DEBUG, GC) << "Clear a " << queue_name_;
79     InternalAllocatorPtr allocator = gc_->GetInternalAllocator();
80     while (!queue_.empty()) {
81         auto task = queue_.top();
82         task->Release(allocator);
83         queue_.pop();
84     }
85 }
86 
87 }  // namespace panda::mem
88