@@ -15,6 +15,7 @@ struct HashMap{K,V} <: AbstractHashMap{K,V}
1515 fd:: Cint
1616end
1717maptype_to_jltype (:: Val{API.BPF_MAP_TYPE_HASH} ) = HashMap
18+ maptype_to_jltype (:: Val{API.BPF_MAP_TYPE_STACK_TRACE} ) = HashMap
1819struct ArrayMap{K,V} <: AbstractArrayMap{K,V}
1920 fd:: Cint
2021end
@@ -45,8 +46,25 @@ struct map_access_elem_attr
4546 flags:: UInt64
4647end
4748
49+ memset! (ptr:: Ptr{T} ) where T =
50+ ccall (:memset , Cvoid,
51+ (Ptr{T}, UInt8, UInt64),
52+ ptr, UInt8 (0 ), sizeof (T))
53+ " Creates a Ref{T} that's been zero-initialized before being stored. Necessary
54+ to ensure that struct padding bytes are zeroed."
55+ function ZeroInitRef (T, val; set= true )
56+ ref = Ref {T} ()
57+ memset! (Base. unsafe_convert (Ptr{T}, ref))
58+ if set
59+ ref[] = val
60+ end
61+ ref
62+ end
63+ ZeroInitRef (val:: T ) where T = ZeroInitRef (T, val)
64+ ZeroInitRef (:: Type{T} ) where T = ZeroInitRef (T, nothing ; set= false )
65+
4866function Base. getindex (map:: AbstractHashMap{K,V} , idx) where {K,V}
49- key = Ref {K} ( idx)
67+ key = ZeroInitRef (K, idx)
5068 value = Ref {V} ()
5169 key_ptr = Base. unsafe_convert (Ptr{K}, key)
5270 value_ptr = Base. unsafe_convert (Ptr{V}, value)
@@ -61,7 +79,7 @@ function Base.getindex(map::AbstractHashMap{K,V}, idx) where {K,V}
6179 value[]
6280end
6381function Base. getindex (map:: AbstractArrayMap{K,V} , idx) where {K,V}
64- key = Ref {K} ( idx- 1 )
82+ key = ZeroInitRef (K, idx- 1 )
6583 value = Ref {V} ()
6684 key_ptr = Base. unsafe_convert (Ptr{K}, key)
6785 value_ptr = Base. unsafe_convert (Ptr{V}, value)
@@ -77,8 +95,8 @@ function Base.getindex(map::AbstractArrayMap{K,V}, idx) where {K,V}
7795end
7896
7997function Base. setindex! (map:: AbstractHashMap{K,V} , value:: U , idx) where {K,V,U}
80- key_ref = Ref {K} (convert (K,idx))
81- value_ref = Ref {V} (convert (V,value))
98+ key_ref = ZeroInitRef (convert (K,idx))
99+ value_ref = ZeroInitRef (convert (V,value))
82100 key_ptr = Base. unsafe_convert (Ptr{K}, key_ref)
83101 value_ptr = Base. unsafe_convert (Ptr{V}, value_ref)
84102 attr = Ref (map_access_elem_attr (map. fd,
@@ -92,8 +110,8 @@ function Base.setindex!(map::AbstractHashMap{K,V}, value::U, idx) where {K,V,U}
92110 value
93111end
94112function Base. setindex! (map:: AbstractArrayMap{K,V} , value:: U , idx) where {K,V,U}
95- key_ref = Ref {K} (convert (K,idx- 1 ))
96- value_ref = Ref {V} (convert (V,value))
113+ key_ref = ZeroInitRef (convert (K,idx- 1 ))
114+ value_ref = ZeroInitRef (convert (V,value))
97115 key_ptr = Base. unsafe_convert (Ptr{K}, key_ref)
98116 value_ptr = Base. unsafe_convert (Ptr{V}, value_ref)
99117 attr = Ref (map_access_elem_attr (map. fd,
@@ -108,7 +126,7 @@ function Base.setindex!(map::AbstractArrayMap{K,V}, value::U, idx) where {K,V,U}
108126end
109127
110128function Base. delete! (map:: AbstractHashMap{K,V} , idx) where {K,V}
111- key = Ref {K} ( idx)
129+ key = ZeroInitRef (K, idx)
112130 key_ptr = Base. unsafe_convert (Ptr{K}, key)
113131 attr = Ref (map_access_elem_attr (map. fd,
114132 key_ptr,
@@ -121,7 +139,7 @@ function Base.delete!(map::AbstractHashMap{K,V}, idx) where {K,V}
121139end
122140
123141function Base. haskey (map:: HostMap{K,V} , idx) where {K,V}
124- key = Ref {K} ( idx)
142+ key = ZeroInitRef (K, idx)
125143 value = Ref {V} ()
126144 key_ptr = Base. unsafe_convert (Ptr{K}, key)
127145 value_ptr = Base. unsafe_convert (Ptr{V}, value)
@@ -134,4 +152,47 @@ function Base.haskey(map::HostMap{K,V}, idx) where {K,V}
134152 end
135153end
136154
137- # TODO : keys(map) using BPF_MAP_GET_NEXT_KEY
155+ function nextkey (map:: HostMap{K,V} , idx) where {K,V}
156+ key = ZeroInitRef (K, idx)
157+ nkey = Ref {K} ()
158+ key_ptr = Base. unsafe_convert (Ptr{K}, key)
159+ nkey_ptr = Base. unsafe_convert (Ptr{K}, nkey)
160+ attr = Ref (map_access_elem_attr (map. fd,
161+ key_ptr,
162+ nkey_ptr,
163+ 0 ))
164+ ret = GC. @preserve key nkey begin
165+ bpf (API. BPF_MAP_GET_NEXT_KEY, attr)
166+ end
167+ if (ret == - 1 ) && (Libc. errno () == Libc. ENOENT)
168+ return nothing
169+ end
170+ ret >= 0 || Base. systemerror (ret)
171+ nkey[]
172+ end
173+
174+ struct HostMapKeySet{K,V,H<: HostMap{K,V} }
175+ map:: H
176+ end
177+ Base. keys (map:: H ) where {K,V,H<: HostMap{K,V} } = HostMapKeySet {K,V,H} (map)
178+ Base. IteratorSize (:: Type{<:HostMapKeySet} ) = Base. SizeUnknown ()
179+ Base. eltype (:: Type{HostMapKeySet{K,V,H}} ) where {K,V,H} = K
180+ function Base. iterate (hmks:: HostMapKeySet{K,V,H} ) where {K,V,H}
181+ fakekey_ref = ZeroInitRef (K)
182+ realkey = if haskey (hmks. map, fakekey_ref[])
183+ fakekey_ref[]
184+ else
185+ nextkey (hmks. map, fakekey_ref[])
186+ end
187+ realkey === nothing && return nothing # empty
188+ return realkey, (realkey, realkey)
189+ end
190+ function Base. iterate (hmks:: HostMapKeySet{K,V,H} , (lastkey, initial)) where {K,V,H}
191+ lastkey === nothing && return nothing
192+ nkey = nextkey (hmks. map, lastkey)
193+ if nkey === nothing || nkey == lastkey
194+ return nothing
195+ end
196+ return nkey, (nkey == initial ? nothing : nkey, initial)
197+ end
198+ Base. length (map:: HostMap ) = length (keys (map))
0 commit comments